diff --git a/.github/workflows/tests.yml b/.github/workflows/digital-signature-tests.yml similarity index 75% rename from .github/workflows/tests.yml rename to .github/workflows/digital-signature-tests.yml index d2954b8..061d181 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/digital-signature-tests.yml @@ -1,4 +1,7 @@ -name: Tests +# This workflow will install Python dependencies, run tests and lint with a single version of Python +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: Digital Signature Tests on: workflow_dispatch: @@ -10,12 +13,6 @@ env: # Purely testing keys that have no access to JP systems etc. PUBLIC: -----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoZ203HV7SOVSu0U9aJa2\nJjAPgyroUH76rKdnPZCgUDKhDcFmNdYC76VXAUL9e9ajVOxIZyBi4FIuZlw2sHMs\nJwXQigxl6B5ZnBn71rkIyXSlvobY3TaTM8of64Wu/1HUgVIueogANTNslF9Kf7nF\ns1HOWWY/H5iVgRPrIXZJ/AjkPCYwlBLUqU58rvogBuaFD1Q14cHJlaxtj/HM1GZS\n4q0Dg6M5EAwZxRtHImliYbIy8zjq2yhY7lKrMdXfK224Ovc1xrY4M875OPz3ppn5\nuChRQqWviFkbCShs83JV6ncfmCmxQRObYQLkDwSAcgPUIWaNM6TUZQwtpZ+1Magi\njwIDAQAB\n-----END PUBLIC KEY----- PRIVATE: -----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQChnbTcdXtI5VK7\nRT1olrYmMA+DKuhQfvqsp2c9kKBQMqENwWY11gLvpVcBQv171qNU7EhnIGLgUi5m\nXDawcywnBdCKDGXoHlmcGfvWuQjJdKW+htjdNpMzyh/rha7/UdSBUi56iAA1M2yU\nX0p/ucWzUc5ZZj8fmJWBE+shdkn8COQ8JjCUEtSpTnyu+iAG5oUPVDXhwcmVrG2P\n8czUZlLirQODozkQDBnFG0ciaWJhsjLzOOrbKFjuUqsx1d8rbbg69zXGtjgzzvk4\n/Pemmfm4KFFCpa+IWRsJKGzzclXqdx+YKbFBE5thAuQPBIByA9QhZo0zpNRlDC2l\nn7UxqCKPAgMBAAECggEAQaVJXXLqzMU5QY/yTZVKD2DeLC01h9zL/W1R5hPkyi6G\ndIvl9GAleSnzmTOYusCIP2pqTlk9UFiROEqkfC+L853NAwXeLtaFF38GaEVoaEvV\nNvqXA+OzDwo+xO/cESEv7AdxkZvEWde1dt7t58uRnjDQXEfHxBG6SF/K1iCyFIjy\nk/+SOnw7Yr2NQwSliXAFBD08zACdJWSy5FCZkGDdyfIc+qCr83CP5jGf0fIKjVDf\nNKfLgUUx5u4XfipznKLSVwL+CDk+uAZumC8Jy/4AE3ip9lgluYBk8KvGGyI3K+rF\nO7ErN7yoV4/pQTAF5XVmsEgbbhUMbYhKJdA++ilPYQKBgQDWVm6MQK8gz0RPwWe0\n6iX+KKj/Pn7/kcHTBSxSLsr9XMHl6uCagIT7ahe0hr6NP2SpoAjoC+sc1C2hYRnO\nQv0y1rBMfbe7huGkqv07bvafmOQVzk8fwmOFwCYzdmpdq+xiQOXZ6CL0uOH7ueOO\nmiGX3x+sr6F6qncalLmh7FoDMwKBgQDBB9EzhRDJmHuADOeKjvwqid0sKabybNZn\n1Rhbq9qD2WS4nOYZk/wuVNgzXfx+b1Hqq8mSKr8IDf0zjMhbxi4i5dJ17d85JzQf\nmTc5eetS4EnVrfEfZPZ7ngO8jpuL8DQtVYLIwnUEKy8ryywvm4kHPBhfb9AqMmav\nm5a/gRSjNQKBgQDRZVtW1hLBwPwB1vcUPfSkGuEPi+TSlXmASPuFxoU1hRtBHXgU\nOR6x6HIEQeeDYr1bIifRW2N0pK13jb+CTNvEgQ13jRKkuB9Vml8PY1a5kMqzqvyO\nEIDeOFyZxkQgA0hKrRBhFHKiFsVgAbkYpefP0YHGWUcu6b62TzoTwS4nFQKBgQCA\nL3HElcwVI/Z3jZpBUDyy/wRqLGraOF6Va1SWo+QjhL03P7IqMDTai6tbSUHAsKok\nfdoI/+wGLEwF7KqtD0laEWaWu9Vt/dPGXBfpSkZ0rc86YB1srL5mTwPKNqWi42uy\n40NLkJ7mmsrjeTOplc8Eh+rjjbweGYRJf7g3CkArNQKBgHosHrZdUYm6OU0JqfC0\nmdhfx3lx51CxGFH/WhhTxngr1EeQOZg5la5MQXOsW4XAWj91uW5nLSPD7yGQH/HM\n7ef20OXlTVdaJEfzf3wc1ZszqyxD0h9J83zxA18sdYIiraMjFf0TJN9sp+n+Kayl\nStjA0osTStTg0tthBjBmDe7L\n-----END PRIVATE KEY----- - COUNTRY_NAME: UK - STATE_OR_PROVINCE_NAME: SCOTLAND - LOCALITY_NAME: Glasgow - ORGANIZATION_NAME: Org - COMMON_NAME: HELLO - DNS_NAME: WORLD permissions: contents: read @@ -24,11 +21,11 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: ./python/sample-authentication-code + working-directory: ./python steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - name: Set up Python 3.10 - uses: actions/setup-python@v5 + uses: actions/setup-python@v3 with: python-version: "3.10" - name: Install dependencies @@ -38,16 +35,33 @@ jobs: if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Test with pytest run: | - cd tests pytest + test-js: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./js + strategy: + matrix: + node-version: [16.x] + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + cache-dependency-path: "./js/yarn.lock" + - run: yarn install --frozen-lockfile + - run: yarn test test-go: runs-on: ubuntu-latest defaults: run: - working-directory: ./go/sample-authentication-code/pkg/samples + working-directory: ./go steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 with: go-version: ">=1.19.0" - run: go test @@ -55,11 +69,11 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: ./java/sample-authentication-code + working-directory: ./java steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v3 - name: Set up JDK 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v3 with: java-version: "17" distribution: "temurin" diff --git a/.github/workflows/metrics.yml b/.github/workflows/metrics.yml index b745ec3..7441923 100644 --- a/.github/workflows/metrics.yml +++ b/.github/workflows/metrics.yml @@ -23,7 +23,7 @@ jobs: ref: metrics - uses: stefanzweifel/git-auto-commit-action@v5 - name: Set up Python 3.10 - uses: actions/setup-python@v5 + uses: actions/setup-python@v3 with: python-version: "3.10" - name: Gather metrics @@ -33,7 +33,7 @@ jobs: python -m pip install --upgrade pip pip install github_traffic_stats if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - gts maria-mcparland:$ACCESS_TOKEN 'authentication' 'save_csv' -o jpmorgan-payments + gts maria-mcparland:$ACCESS_TOKEN 'digital-signature' 'save_csv' -o jpmorgan-payments ls - name: Run merge script run: | diff --git a/.gitignore b/.gitignore index fce69e3..e940a5e 100644 --- a/.gitignore +++ b/.gitignore @@ -129,14 +129,6 @@ dist .yarn/install-state.gz .pnp.* -# npm -package-lock.json - __pycache__ launch.json -target -.pytest_cache - - -application-local.yml -.idea \ No newline at end of file +target \ No newline at end of file diff --git a/README.md b/README.md index a341de4..88f606f 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,31 @@ -# J.P. Morgan Authentication examples +# Generate a Digital Signature for hitting payments APIs -Within this repository you can find example code for accessing our Payments APIs. -We have split the code by programming language for ease of use. -Each folder contains: +When accessing our Payments API we require a Digital Signature (also known as JWT Token) to be used as a post body. +This digital signature is an encoded version of your JSON body. -- sample-authentication-code: This contains code scripts for generating digital signatures (also known as JWTs), gathering access tokens and generating certificates. -- backend-example: This is a fully functioning server that can handle sending requests to our APIs. (Coming soon to all languages!) +This example code shows you how to generate the digital signature to hit the POST endpoints on our APIs. +We have generated the initial code using the ChatGPT API and then corrected errors manually. -**Note this is not production code and is supplied to get developers started ** +## How to run locally + +You can manually clone and configure the example yourself: + +``` +git clone https://github.com/jpmorgan-payments/digital-signature.git +``` + +This example includes several different language implementations. + +Pick a programming langauge: + +- [Go](./go/) +- [JavaScript](./js/) +- [Python](./python/) +- [Java](./java/) ### Generating test certificates -You can follow the below commands to get setup with some testing certificates. To use these against J.P. Morgan APIs you will need to onboard them on [developer.jpmorgan.com](https://developer.jpmorgan.com) +You can follow the below commands to get setup with some testing certificates. To use these against J.P. Morgan APIs you will need to onboard them on [developer.jpmorgan.com](developer.jpmorgan.com) ```bash openssl genrsa -out keypair.pem 2048 diff --git a/certificates/README.md b/certificates/README.md deleted file mode 100644 index d48e9f5..0000000 --- a/certificates/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Certificates - -Public J.P. Morgan certificates coming soon... diff --git a/go/README.md b/go/README.md new file mode 100644 index 0000000..586c2c9 --- /dev/null +++ b/go/README.md @@ -0,0 +1,27 @@ +# Digital Signature GoLang snippet + +A snippet of Golang code to show how to create a digital signature + +## Requirements + +- Go installed +- [Configured .env file](../README.md) + +## How to run + +You can run this code by running the tests or by including it in your codebase. + +1. Confirm `.env` configuration + +Ensure the certificate keys are configured in `.env` in this directory. You can find information on generating certificates at in our [readme](../README.md). It should include the following keys: + +```yaml +PRIVATE=... +PUBLIC= +``` + +2. Install dependencies and start the server + +``` +go test +``` diff --git a/go/backend-example/README.md b/go/backend-example/README.md deleted file mode 100644 index 4dd90c6..0000000 --- a/go/backend-example/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Go Backend Samples - -There are two code samples in this folder for connecting to our APIs using Go. -Each sample is categorised by the authentication method you will use. - -** Note this is not production code and is supplied to get developers started ** - -## Requirements - -- Go 1.19 - -## How to run - OAuth - -1. Enter your access token url, client_id and client_secret in the file. - -2. Start the server - -``` -go run . -``` - -3. Import the postman collection at the top of this repo to test out the server connection, you can use folder 'backend-examples'. Instructions for importing postman collections can be found ([here](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)) - -## How to run - SSL - -1. Enter your certificates pathd in the file.To upload your certificates you will need to onboard to [https://developer.jpmorgan.com](https://developer.jpmorgan.com) -2. Start the server - -``` -go run . -``` - -3. Import the postman collection at the top of this repo to test out the server connection, you can use folder 'backend-examples'. Instructions for importing postman collections can be found ([here](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)) diff --git a/go/backend-example/oauth/go.mod b/go/backend-example/oauth/go.mod deleted file mode 100644 index 72de741..0000000 --- a/go/backend-example/oauth/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module backend-example/oauth - -go 1.19 diff --git a/go/backend-example/oauth/proxy.go b/go/backend-example/oauth/proxy.go deleted file mode 100644 index d3d7525..0000000 --- a/go/backend-example/oauth/proxy.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -/* -This code is a simple example of how to run a backend server for OAuth connections. -You can send your request to localhost:8001/ -This code will receive the request, gather the OAuth token and then forward it to our servers. -You will need to provide your ACCESS_TOKEN_URL, CLIENT_ID, CLIENT_SECRET as command line arguments -You can run with: 'go run . --url="enter url" --id="enter client id" --secret="secret"' -You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start -If you are hitting our APIs that require a digital signature or JWT then provide your key as a command line argument -Note this is not production code and is supplied to get developers started -*/ - -import ( - "bytes" - "encoding/json" - "flag" - "io" - "log" - "net/http" - "net/http/httputil" - "net/url" - "sample_authentication_code/pkg/samples" -) - -func main() { - remote, err := url.Parse("https://api-mock.payments.jpmorgan.com") - if err != nil { - log.Fatal(err) - } - access_token_url := flag.String("url", "access_token_url", "an access token url") - client_id := flag.String("id", "client_id", "client id") - client_secret := flag.String("secret", "client_secret", "client_secret") - // If digital key is defined we will encode the payload - digital_key := flag.String("key", "digital_key", "digital_key") - flag.Parse() - - handler := func(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - log.Println(r.URL) - r.Host = remote.Host - // Access token generation. We are using the code from our sample authentication folder - accessToken, err := samples.GetAccessToken(*access_token_url, *client_id, *client_secret) - if err != nil { - log.Fatalf("Error getting access token: %v", err) - } - w.Header().Set("Authorization", "Bearer "+accessToken) - // JWT/Digital Signature generation. This is required for some of our POST requests. - if len(*digital_key) != 0 { - modifyRequestBody(w, r, *digital_key) - } - - p.ServeHTTP(w, r) - } - } - - proxy := httputil.NewSingleHostReverseProxy(remote) - http.HandleFunc("/", handler(proxy)) - err = http.ListenAndServe(":8001", nil) - if err != nil { - log.Fatal(err) - } -} - -func modifyRequestBody(w http.ResponseWriter, r *http.Request, digital_key string) { - var body map[string]interface{} - err := json.NewDecoder(r.Body).Decode(&body) - if err != nil { - log.Printf("Error decoding request body: %v", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - digitalSignature := []byte(samples.GenerateDigitalSignature(digital_key, body)) - r.Body = io.NopCloser(bytes.NewBuffer(digitalSignature)) - r.ContentLength = int64(len(digitalSignature)) -} diff --git a/go/backend-example/ssl/go.mod b/go/backend-example/ssl/go.mod deleted file mode 100644 index 070c2c2..0000000 --- a/go/backend-example/ssl/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module backend-example/ssl - -go 1.19 diff --git a/go/backend-example/ssl/proxy.go b/go/backend-example/ssl/proxy.go deleted file mode 100644 index e57db54..0000000 --- a/go/backend-example/ssl/proxy.go +++ /dev/null @@ -1,91 +0,0 @@ -package main - -/* -This code is a simple example of how to run a backend server for SSL connections. -You can send your request to localhost:8001/ -This code will receive the request, add the certs and then forward it to our servers. -You will provide your PRIVATE and PUBLIC file paths. -You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start -If you are hitting our APIs that require a digital signature or JWT then provide your key as a command line value.E.g: -You can run with: 'go run . -key="your key here' -Note this is not production code and is supplied to get developers started -*/ - -import ( - "bytes" - "crypto/tls" - "encoding/json" - "flag" - "io" - "log" - "net/http" - "net/http/httputil" - "net/url" - "sample_authentication_code/pkg/samples" -) - -func main() { - // Parse the remote URL - remote, err := url.Parse("https://api-mock.payments.jpmorgan.com") - if err != nil { - log.Fatal(err) - } - // If digital key is defined we will encode the payload - digital_key := flag.String("key", "digital_key", "digital_key") - flag.Parse() - - // Load client certificate and key - cert, err := tls.LoadX509KeyPair("client.crt", "client.key") - if err != nil { - log.Fatal(err) - } - - // Configure TLS with client certificate (skip CA certificate verification) - tlsConfig := &tls.Config{ - Certificates: []tls.Certificate{cert}, - InsecureSkipVerify: true, // Skip CA certificate verification - } - - // Create a HTTP client with custom TLS configuration - client := &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: tlsConfig, - }, - } - - // Define the reverse proxy handler - handler := func(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - log.Println(r.URL) - r.Host = remote.Host - - // JWT/Digital Signature generation. This is required for some of our POST requests. - modifyRequestBody(w, r, *digital_key) - p.ServeHTTP(w, r) - } - } - - // Create a reverse proxy with the remote URL and custom HTTP client - proxy := httputil.NewSingleHostReverseProxy(remote) - proxy.Transport = client.Transport - - // Register the handler and start the server - http.HandleFunc("/", handler(proxy)) - err = http.ListenAndServe(":8001", nil) - if err != nil { - log.Fatal(err) - } -} - -func modifyRequestBody(w http.ResponseWriter, r *http.Request, digital_key string) { - var body map[string]interface{} - err := json.NewDecoder(r.Body).Decode(&body) - if err != nil { - log.Printf("Error decoding request body: %v", err) - http.Error(w, "Internal Server Error", http.StatusInternalServerError) - return - } - digitalSignature := []byte(samples.GenerateDigitalSignature(digital_key, body)) - r.Body = io.NopCloser(bytes.NewBuffer(digitalSignature)) - r.ContentLength = int64(len(digitalSignature)) -} diff --git a/go/digital_signature.go b/go/digital_signature.go new file mode 100644 index 0000000..a58d22e --- /dev/null +++ b/go/digital_signature.go @@ -0,0 +1,18 @@ +package digital_signature + +import ( + "fmt" + + "github.com/golang-jwt/jwt/v5" +) + +func generate_digital_signature(digital_key string, body map[string]interface{}) string { + token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims(body)) + signKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(digital_key)) + + tokenString, err := token.SignedString(signKey) + if err != nil { + fmt.Println(err) + } + return tokenString +} diff --git a/go/sample-authentication-code/pkg/samples/getJWT_test.go b/go/digital_signature_test.go similarity index 75% rename from go/sample-authentication-code/pkg/samples/getJWT_test.go rename to go/digital_signature_test.go index 29fdd7e..629ac93 100644 --- a/go/sample-authentication-code/pkg/samples/getJWT_test.go +++ b/go/digital_signature_test.go @@ -1,24 +1,24 @@ -package samples +package digital_signature import ( - "fmt" - "os" - "strings" - "testing" - - "github.com/golang-jwt/jwt/v5" + "fmt" + "testing" + "os" "github.com/joho/godotenv" + "github.com/golang-jwt/jwt/v5" + "strings" ) + func setupSuite(t testing.TB) string { godotenv.Load() - return os.Getenv("PRIVATE") + return os.Getenv("PRIVATE") } -func TestDigSignGenerated(t *testing.T) { - privateKey := strings.ReplaceAll(setupSuite(t), "\\n", "\n") +func TestDigSignGenerated(t *testing.T) { + privateKey := strings.ReplaceAll(setupSuite(t), "\\n", "\n") - result := GenerateDigitalSignature(privateKey, map[string]interface{}{"foo": "bar"}) + result := generate_digital_signature(privateKey, map[string]interface{}{"foo": "bar"}) // Verify that the token can be parsed and verified token, err := jwt.Parse(result, func(token *jwt.Token) (interface{}, error) { // Verify that the signing method is RS256 @@ -41,4 +41,4 @@ func TestDigSignGenerated(t *testing.T) { if !token.Valid { t.Errorf("Invalid token") } -} +} \ No newline at end of file diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 0000000..38a4343 --- /dev/null +++ b/go/go.mod @@ -0,0 +1,8 @@ +module digital_signature + +go 1.19 + +require ( + github.com/golang-jwt/jwt/v5 v5.1.0 + github.com/joho/godotenv v1.5.1 +) diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 0000000..a26692e --- /dev/null +++ b/go/go.sum @@ -0,0 +1,6 @@ +github.com/golang-jwt/jwt/v5 v5.0.0-rc.1 h1:tDQ1LjKga657layZ4JLsRdxgvupebc0xuPwRNuTfUgs= +github.com/golang-jwt/jwt/v5 v5.0.0-rc.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.1.0 h1:UGKbA/IPjtS6zLcdB7i5TyACMgSbOTiR8qzXgw8HWQU= +github.com/golang-jwt/jwt/v5 v5.1.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= diff --git a/go/go.work b/go/go.work deleted file mode 100644 index 38b3c32..0000000 --- a/go/go.work +++ /dev/null @@ -1,7 +0,0 @@ -go 1.19 - -use ( - ./backend-example/oauth - ./backend-example/ssl - ./sample-authentication-code -) diff --git a/go/sample-authentication-code/README.md b/go/sample-authentication-code/README.md deleted file mode 100644 index a2eadea..0000000 --- a/go/sample-authentication-code/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# GoLang snippets - -A collection of scripts for helping you to generate certificates, get access tokens for OAuth, encode your payloads and sending a first request. diff --git a/go/sample-authentication-code/cmd/main.go b/go/sample-authentication-code/cmd/main.go deleted file mode 100644 index 8877257..0000000 --- a/go/sample-authentication-code/cmd/main.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -/* -This shows how to gather an access token and then send your first request to our OAuth protected APIs. -You will need to provide API_URL, ACCESS_TOKEN_URL, CLIENT_ID, CLIENT_SECRET and the payload. -You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start -* */ - -import ( - "fmt" - "sample_authentication_code/pkg/samples" - "strings" -) - -func main() { - api_url := "" - access_token_url := "" - client_id := "" - client_secret := "" - payload := strings.NewReader("{}") - accessToken, err := samples.GetAccessToken(access_token_url, client_id, client_secret) - if err != nil { - fmt.Printf("Error getting access token: %v", err) - } else { - samples.SendFirstRequest(payload, api_url, accessToken) - } -} diff --git a/go/sample-authentication-code/go.mod b/go/sample-authentication-code/go.mod deleted file mode 100644 index a9f79a9..0000000 --- a/go/sample-authentication-code/go.mod +++ /dev/null @@ -1,7 +0,0 @@ -module sample_authentication_code - -go 1.19 - -require github.com/golang-jwt/jwt/v5 v5.2.0 - -require github.com/joho/godotenv v1.5.1 diff --git a/go/sample-authentication-code/go.sum b/go/sample-authentication-code/go.sum deleted file mode 100644 index fe7fc97..0000000 --- a/go/sample-authentication-code/go.sum +++ /dev/null @@ -1,4 +0,0 @@ -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= diff --git a/go/sample-authentication-code/pkg/samples/generateCertificates.go b/go/sample-authentication-code/pkg/samples/generateCertificates.go deleted file mode 100644 index b65f8a5..0000000 --- a/go/sample-authentication-code/pkg/samples/generateCertificates.go +++ /dev/null @@ -1,69 +0,0 @@ -package samples - -/* -* This utility script is used to create a certificate request (CSR) along with a self-signed X509 certificate (CRT) using -* crypto which is a go library containing various cryptography utilities to create and handle communicate protocols. -* -* generateCertificates.go is a script that will ask for various information that is incorporated into your certificate request -* which can then be used with an approved certificate authority (CA) to receive a signed certificate to on-board to PROD environment. -* The script will also generate a self-signed certificate using basic extensions that can be used to on-board to CAT environment. -* -* */ - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "fmt" - "math/big" - "os" - "time" -) - -func GenerateSelfSignedCert(countryName, stateOrProvinceName, localityName, organizationName, commonName, dnsName string) error { - // Generate a private key - privateKey, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - return err - } - - // Create a certificate template - template := x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{Country: []string{countryName}, Province: []string{stateOrProvinceName}, Locality: []string{localityName}, Organization: []string{organizationName}, CommonName: commonName}, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(1, 0, 0), // Expires after 365 days - BasicConstraintsValid: true, - IsCA: true, - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}, - DNSNames: []string{dnsName}, - } - - // Create a self-signed certificate - derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privateKey.PublicKey, privateKey) - if err != nil { - return err - } - - // Write the certificate to a file - certOut, err := os.Create("certificate.pem") - if err != nil { - return err - } - defer certOut.Close() - pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) - - // Write the private key to a file - keyOut, err := os.Create("./private_key.pem") - if err != nil { - return err - } - defer keyOut.Close() - pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)}) - - fmt.Println("Certificate and private key generated successfully.") - return nil -} diff --git a/go/sample-authentication-code/pkg/samples/generateCertificates_test.go b/go/sample-authentication-code/pkg/samples/generateCertificates_test.go deleted file mode 100644 index a009be5..0000000 --- a/go/sample-authentication-code/pkg/samples/generateCertificates_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package samples - -import ( - "os" - "testing" -) - -func TestGenerateSelfSignedCert(t *testing.T) { - // Call the function with test certificate details - err := GenerateSelfSignedCert("US", "California", "San Francisco", "My Organization", "localhost", "localhost") - if err != nil { - t.Errorf("Error generating certificate: %v", err) - } - - // Check if the certificate and private key files are generated - _, certErr := os.Stat("certificate.pem") - _, keyErr := os.Stat("private_key.pem") - if os.IsNotExist(certErr) || os.IsNotExist(keyErr) { - t.Errorf("Certificate or private key file is not generated") - } - - // Clean up generated files - os.Remove("certificate.pem") - os.Remove("private_key.pem") -} diff --git a/go/sample-authentication-code/pkg/samples/getAccessToken.go b/go/sample-authentication-code/pkg/samples/getAccessToken.go deleted file mode 100644 index e71f33a..0000000 --- a/go/sample-authentication-code/pkg/samples/getAccessToken.go +++ /dev/null @@ -1,52 +0,0 @@ -package samples - -/* -This snippet highlights how to obtain an OAuth access token using gO. -You will provide your CLIENT_ID, CLIENT_SECRET and ACCESS_TOKEN_URL. -You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start -*/ - -import ( - "encoding/json" - "fmt" - "net/http" - "strings" -) - -func GetAccessToken(url, clientID, clientSecret string) (string, error) { - // Prepare request body - payload := strings.NewReader("grant_type=client_credentials&scope=jpm:payments:sandbox") - - // Create HTTP client - httpClient := &http.Client{} - - // Create HTTP request - req, err := http.NewRequest("POST", url, payload) - if err != nil { - return "", err - } - req.SetBasicAuth(clientID, clientSecret) - req.Header.Add("Content-Type", "application/x-www-form-urlencoded") - - // Send request - resp, err := httpClient.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - // Decode response - var responseMap map[string]interface{} - err = json.NewDecoder(resp.Body).Decode(&responseMap) - if err != nil { - return "", err - } - - // Extract access token from response - accessToken, ok := responseMap["access_token"].(string) - if !ok { - return "", fmt.Errorf("access token not found in response") - } - - return accessToken, nil -} diff --git a/go/sample-authentication-code/pkg/samples/getAccessToken_test.go b/go/sample-authentication-code/pkg/samples/getAccessToken_test.go deleted file mode 100644 index 8ad7b96..0000000 --- a/go/sample-authentication-code/pkg/samples/getAccessToken_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package samples - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -func TestGetAccessToken(t *testing.T) { - // Create a mock HTTP server to handle the request - mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - - // Respond with a mock access token - w.Header().Set("Content-Type", "application/json") - w.Write([]byte(`{"access_token": "mock_access_token"}`)) - })) - defer mockServer.Close() - - // Call the function with the URL of the mock server - accessToken, err := GetAccessToken(mockServer.URL+"/token", "client_id", "client_secret") - if err != nil { - t.Errorf("Error getting access token: %v", err) - } - // Verify that the access token is correct - expectedAccessToken := "mock_access_token" - if accessToken != expectedAccessToken { - t.Errorf("Expected access token %s, got %s", expectedAccessToken, accessToken) - } -} diff --git a/go/sample-authentication-code/pkg/samples/getJWT.go b/go/sample-authentication-code/pkg/samples/getJWT.go deleted file mode 100644 index 9e9b0ab..0000000 --- a/go/sample-authentication-code/pkg/samples/getJWT.go +++ /dev/null @@ -1,24 +0,0 @@ -package samples - -/* -This snippet is to show you how to generate a JWT/Digital Signature for sending post requests to our payments APIs. -You will need to provide your signing key and the body you wish to encode. -*/ -import ( - "fmt" - - "github.com/golang-jwt/jwt/v5" -) - -func GenerateDigitalSignature(digital_key string, body map[string]interface{}) string { - token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims(body)) - signKey, err := jwt.ParseRSAPrivateKeyFromPEM([]byte(digital_key)) - if err != nil { - fmt.Println(err) - } - tokenString, err := token.SignedString(signKey) - if err != nil { - fmt.Println(err) - } - return tokenString -} diff --git a/go/sample-authentication-code/pkg/samples/sendFirstRequest.go b/go/sample-authentication-code/pkg/samples/sendFirstRequest.go deleted file mode 100644 index 99e1dd2..0000000 --- a/go/sample-authentication-code/pkg/samples/sendFirstRequest.go +++ /dev/null @@ -1,30 +0,0 @@ -package samples - -/* -This shows how to send your first request to our OAuth protected APIs. -It takes in a payload, API Url and then an access token. -* */ - -import ( - "fmt" - "io" - "net/http" -) - -func SendFirstRequest(payload io.Reader, url string, accessToken string) { - - req, _ := http.NewRequest("POST", url, payload) - - req.Header.Add("Content-Type", "application/json") - req.Header.Add("Accept", "application/json") - req.Header.Add("Authorization", "Bearer "+accessToken) - - res, _ := http.DefaultClient.Do(req) - - defer res.Body.Close() - body, _ := io.ReadAll(res.Body) - - fmt.Println(res) - fmt.Println(string(body)) - -} diff --git a/go/sample-authentication-code/pkg/samples/sendFirstRequest_test.go b/go/sample-authentication-code/pkg/samples/sendFirstRequest_test.go deleted file mode 100644 index 6f686f5..0000000 --- a/go/sample-authentication-code/pkg/samples/sendFirstRequest_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package samples - -import ( - "io/ioutil" - "net/http" - "net/http/httptest" - "strings" - "testing" -) - -func TestSendFirstRequest(t *testing.T) { - // Define the test payload, URL, and access token - testPayload := strings.NewReader(`{"key": "value"}`) - testURL := "https://example.com/api" - testAccessToken := "abc123" - - // Create a new instance of the test server with a handler function - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Check if the request method is POST - if r.Method != http.MethodPost { - t.Errorf("Expected POST request, got %s", r.Method) - return - } - - // Check if the request URL matches - if r.URL.String() != testURL { - t.Errorf("Expected request URL to be %s, got %s", testURL, r.URL.String()) - return - } - - // Read request body - body, err := ioutil.ReadAll(r.Body) - if err != nil { - t.Errorf("Error reading request body: %v", err) - return - } - - // Check if the request body matches the expected payload - expectedPayload := `{"key": "value"}` - if string(body) != expectedPayload { - t.Errorf("Expected request body:\n%s\nGot:\n%s", expectedPayload, string(body)) - return - } - - // Respond with a predefined response - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - // You can customize the response body as needed for your test - responseBody := `{"status": "success"}` - w.Write([]byte(responseBody)) - })) - - // Close the server when the test finishes - defer ts.Close() - - // Call the function being tested - SendFirstRequest(testPayload, testURL, testAccessToken) -} diff --git a/java/README.md b/java/README.md index e4df07a..efd19f7 100644 --- a/java/README.md +++ b/java/README.md @@ -1,10 +1,16 @@ -# J.P. Morgan Authentication examples - Java +# Digital Signature Java -Within this repository you can find example code for accessing our Payments APIs in Java. +A Java implementation of generating a digital signature -Each folder contains: +## Requirements -- sample-authentication-code: This contains code scripts for generating digital signatures (also known as JWTs), gathering access tokens and generating certificates. -- backend-example: This is a fully functioning server that can handle sending requests to our APIs. +- Java installed +- Configured environment variables -**Note this is not production code and is supplied to get developers started ** +## How to run + +You can run this code by running the tests or by including it in your codebase. + +1. Add your PUBLIC/PRIVATE key into environment variables. You can find information on generating certificates at in our [readme](../README.md) + +2. Run the test in [the test folder](./src/test/java/com/jpmorgan/payments/digital_signature/JWTTest.java) diff --git a/java/backend-example/README.md b/java/backend-example/README.md deleted file mode 100644 index a508ae0..0000000 --- a/java/backend-example/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Java Backend Samples - -In this folder there are two code samples for connecting to our APIs using Java. -Each sample is categorised by the authentication method you will use. - -** Note this is not production code and is supplied to get developers started ** - -## Requirements - -- Java and maven installed - -## How to run - OAuth - -1. You will require CLIENT_ID, CLIENT_SECRET and ACCESS_TOKEN_URL to run this code. - You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start. - Insert them into your application-local.yml file. -2. Ensure profile "local" is activated -3. Update line 23 in [Digital Signature Generator](./src/main/java/com/jpmorgan/payments/sample/DigitalSignatureGenerator.java) to match your digital signature key file. -4. Import the postman collection at the top of this repo to test out the server connection, you can use folder 'backend-examples'. Instructions for importing postman collections can be found ([here](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)) - -## How to run - SSL - -1. You will need to setup a java keystore using your transport certificates. The below commands can be used to achieve this: - -\*\* Make sure you remember the passwords you enter as you will need these later on \*\* - -```bash -openssl pkcs12 -export -in transport.crt -inkey transport.key -out keystore.p12 -name "mykey" -keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -destkeystore truststore.jks -deststoretype JKS -``` - -2. We have provided an application.yml with some base setup. We recommend setting up an application-local.yml file with the path and password to your keystore. Do not commit this file. - -```yml -ssl: - keystore: - location: - password: -``` - -2. Ensure profile "local" is activated -3. Update line 23 in [Digital Signature Generator](./src/main/java/com/jpmorgan/payments/sample/DigitalSignatureGenerator.java) to match your digital signature key file -4. Import the postman collection at the top of this repo to test out the server connection, you can use folder 'backend-examples'. Instructions for importing postman collections can be found ([here](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)) diff --git a/java/backend-example/oauth/pom.xml b/java/backend-example/oauth/pom.xml deleted file mode 100644 index ec78e6a..0000000 --- a/java/backend-example/oauth/pom.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.0.5 - - - com.jpmorgan.payments - sample - 0.0.1-SNAPSHOT - sample - Sample project for OAuth connections - - 21 - - - - org.springframework.boot - spring-boot-starter-web - - - io.jsonwebtoken - jjwt-api - 0.11.5 - - - io.jsonwebtoken - jjwt-impl - 0.11.5 - - - io.jsonwebtoken - jjwt-jackson - 0.11.5 - - - - org.apache.httpcomponents.client5 - httpclient5 - 5.1.3 - - - - org.apache.httpcomponents.client5 - httpclient5-fluent - 5.1.3 - - - org.apache.httpcomponents.core5 - httpcore5 - - - javax.xml.bind - jaxb-api - 2.4.0-b180830.0359 - - - org.json - json - 20231013 - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/DigitalSignatureGenerator.java b/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/DigitalSignatureGenerator.java deleted file mode 100644 index 967af29..0000000 --- a/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/DigitalSignatureGenerator.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.jpmorgan.payments.sample; - -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyFactory; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import org.json.JSONObject; -import org.springframework.stereotype.Service; - -import javax.xml.bind.DatatypeConverter; - -@Service -public class DigitalSignatureGenerator - -{ - String privateKeyFilename = "./src/main/resources/static/private.key"; - - private static String formatKeyString(String key) { - return key.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "") - .replace("\\n", "").replaceAll("\\s+", ""); - } - - /** - * Method for reading in a private key and preparing it for signing - * - * @return a Private Key object - */ - private PrivateKey gatherPrivateKey() { - byte[] keyBytes = readCertFile(privateKeyFilename); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); - PrivateKey prvKey = null; - try { - KeyFactory kf = KeyFactory.getInstance("RSA"); - prvKey = kf.generatePrivate(keySpec); - - } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { - // TODO Proper error handling is required here - e.printStackTrace(); - } - return prvKey; - } - - private byte[] readCertFile(String filename) { - try { - String key = Files.readString(Paths.get(filename)); - return DatatypeConverter.parseBase64Binary(formatKeyString(key)); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private JSONObject formatPaymentAmountField(String payload) { - final JSONObject payloadObj = new JSONObject(payload); - JSONObject payments = payloadObj.getJSONObject("payments"); - String amount = payments.getString("paymentAmount"); - payments.put("paymentAmount", Double.parseDouble(amount)); - payloadObj.put("payments", payments); - return payloadObj; - } - - /** - * Method for signing a JSON payload - * - * @param payload The JSON payload to be digitally signed. - * @return - */ - public String createJWT(String payload) { - - // The JWT signature algorithm we will be using to sign the token - SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256; - - // Prepare your private key for signing - PrivateKey prvKey = gatherPrivateKey(); - JSONObject payments = formatPaymentAmountField(payload); - - return Jwts.builder().setClaims(payments.toMap()) - .signWith(prvKey, signatureAlgorithm).compact(); - - } -} diff --git a/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/PaymentsController.java b/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/PaymentsController.java deleted file mode 100644 index 3e63848..0000000 --- a/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/PaymentsController.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.jpmorgan.payments.sample; - -import jakarta.servlet.http.HttpServletRequest; -import org.json.JSONObject; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; - -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import com.jpmorgan.payments.sample.DigitalSignatureGenerator; - -import java.io.IOException; -import java.net.URI; -import java.net.URLEncoder; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -@SpringBootApplication -@RestController -public class PaymentsController { - - private static final String API_URL = "https://api-mock.payments.jpmorgan.com"; - - @Value("${ACCESS_TOKEN_URL}") - private String ACCESS_TOKEN_URL; - - @Value("${CLIENT_ID}") - private String CLIENT_ID; - - @Value("${CLIENT_SECRET}") - private String CLIENT_SECRET; - - @Autowired - private DigitalSignatureGenerator digitalSignatureGenerator; - - private final HttpClient httpClient; - - @Autowired - public PaymentsController(HttpClient httpClient) { - this.httpClient = httpClient; - } - - /** - * A reverse proxy that forwards requests to the J.P. Morgan API and returns the - * response to the client. - * The reverse proxy should use the OAuth 2.0 client credentials flow to - * authenticate with the J.P. Morgan API. - * The reverse proxy should be able to handle multiple concurrent requests. - * The reverse proxy should log the request and response payloads to the - * console. - * The reverse proxy should return a 502 Bad Gateway if the J.P. Morgan API is - * unavailable. - */ - - @RequestMapping(value = "/**") - public ResponseEntity proxyRequest(@RequestBody(required = false) String body, - @RequestHeader Map headers, - @RequestParam Map params, - HttpServletRequest request) throws IOException, InterruptedException { - String method = request.getMethod(); - String path = request.getRequestURI(); - String url = API_URL + path; - String query = params.entrySet().stream() - .map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) + "=" - + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8)) - .collect(Collectors.joining("&")); - if (!query.isEmpty()) { - url += "?" + query; - } - HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() - .uri(URI.create(url)) - .header("Content-Type", "application/json") - .header("Authorization", "Bearer " + getAccessToken()); - HttpRequest newRequest = switch (method) { - case "GET" -> requestBuilder.GET().build(); - case "POST" -> - requestBuilder.POST(HttpRequest.BodyPublishers.ofString(handlePostBodyEncoding(body))).build(); - case "PUT" -> requestBuilder.PUT(HttpRequest.BodyPublishers.ofString(body)).build(); - case "DELETE" -> requestBuilder.DELETE().build(); - default -> throw new IllegalArgumentException("Unsupported request method: " + method); - }; - HttpResponse response = httpClient.send(newRequest, - HttpResponse.BodyHandlers.ofString()); - return ResponseEntity.status(response.statusCode()).body(response.body()); - } - - private String handlePostBodyEncoding(String body) { - return digitalSignatureGenerator.createJWT(body); - } - - /** - * A method that uses the OAuth 2.0 client credentials flow to - * authenticate with the J.P. Morgan API and returns the access token.ยง - */ - - private String getAccessToken() { - Map parameters = new HashMap<>(); - parameters.put("grant_type", "client_credentials"); - parameters.put("client_id", CLIENT_ID); - parameters.put("client_secret", CLIENT_SECRET); - parameters.put("scope", "jpm:payments:sandbox"); - String form = parameters.keySet().stream() - .map(key -> key + "=" + URLEncoder.encode(parameters.get(key), StandardCharsets.UTF_8)) - .collect(Collectors.joining("&")); - - HttpRequest request = HttpRequest.newBuilder().uri(URI.create(ACCESS_TOKEN_URL)) - .headers("Content-Type", "application/x-www-form-urlencoded") - .POST(HttpRequest.BodyPublishers.ofString(form)).build(); - - HttpResponse response = null; - try { - response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - JSONObject obj = new JSONObject(response.body().toString()); - String accessToken = obj.getString("access_token"); - - System.out.println(response.statusCode() + response.body().toString()); - return accessToken; - } - -} diff --git a/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/SampleApplication.java b/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/SampleApplication.java deleted file mode 100644 index 20274bd..0000000 --- a/java/backend-example/oauth/src/main/java/com/jpmorgan/payments/sample/SampleApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.jpmorgan.payments.sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SampleApplication { - - public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); - } - -} diff --git a/java/backend-example/oauth/src/main/resources/application.yml b/java/backend-example/oauth/src/main/resources/application.yml deleted file mode 100644 index 5b39cdb..0000000 --- a/java/backend-example/oauth/src/main/resources/application.yml +++ /dev/null @@ -1,6 +0,0 @@ -server: - port: 8001 - -ACCESS_TOKEN_URL: -CLIENT_ID: -CLIENT_SECRET: diff --git a/java/backend-example/ssl/pom.xml b/java/backend-example/ssl/pom.xml deleted file mode 100644 index c21a381..0000000 --- a/java/backend-example/ssl/pom.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.0.5 - - - com.jpmorgan.payments - sample - 0.0.1-SNAPSHOT - sample - Sample project for Global Payments - - 20 - - - - org.springframework.boot - spring-boot-starter-web - - - io.jsonwebtoken - jjwt-api - 0.11.5 - - - io.jsonwebtoken - jjwt-impl - 0.11.5 - - - io.jsonwebtoken - jjwt-jackson - 0.11.5 - - - - org.apache.httpcomponents.client5 - httpclient5 - 5.1.3 - - - - org.apache.httpcomponents.client5 - httpclient5-fluent - 5.1.3 - - - org.apache.httpcomponents.core5 - httpcore5 - - - javax.xml.bind - jaxb-api - 2.4.0-b180830.0359 - - - org.json - json - 20231013 - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/PaymentsController.java b/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/PaymentsController.java deleted file mode 100644 index 8638c51..0000000 --- a/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/PaymentsController.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.jpmorgan.payments.sample; - -import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; -import org.apache.hc.client5.http.io.HttpClientConnectionManager; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; -import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactoryBuilder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.*; -import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; -import org.springframework.util.ResourceUtils; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.client.RestTemplate; - -import java.io.*; - -import org.apache.hc.client5.http.classic.HttpClient; -import org.apache.hc.client5.http.impl.classic.HttpClients; - - -import javax.net.ssl.*; -import java.security.KeyStore; - -@RestController -@RequestMapping("/api/digitalSignature") -public class PaymentsController { - - @Value("${ssl.keystore.location}") - private String keystorePath; - - @Value("${ssl.keystore.password}") - private String keystorePassword; - - @Value("${api.globalPaymentsPath}") - private String globalPaymentsPath; - @Value("${api.cat.url}") - private String url; - @Autowired - DigitalSignatureGenerator digitalSignatureGenerator; - @PostMapping("/tsapi/v1/payments") - public ResponseEntity digitalSignature(@RequestBody String body) throws Exception { - String digitalSignature = digitalSignatureGenerator.createJWT(body); - String outgoingUrl = url + globalPaymentsPath; - RestTemplate restTemplate = generateRestTemplate(); - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.TEXT_XML); - - HttpEntity entity = new HttpEntity<>(digitalSignature, headers); - return restTemplate.exchange(outgoingUrl, HttpMethod.POST, entity, String.class); - } - private RestTemplate generateRestTemplate () throws Exception { - KeyStore keyStore = keyStore(keystorePath); - - // Create a KeyManagerFactory using the keystore - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(keyStore, keystorePassword.toCharArray()); - - // We are only doing 1-way SSL for the code samples - TrustManager[] trustAllCerts = new TrustManager[] { new TrustAllManager() }; - - - // Create an SSLContext using the KeyManagerFactory and TrustManagerFactory - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, null); - - final SSLConnectionSocketFactory sslSocketFactory = SSLConnectionSocketFactoryBuilder.create() - .setSslContext(sslContext) - .build(); - - final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() - .setSSLSocketFactory(sslSocketFactory) - .build(); - - // Create an HttpClient with the SSLContext and a custom hostname verifier - HttpClient httpClient = HttpClients.custom() - .setConnectionManager(cm) - .build(); - - // Create an HttpComponentsClientHttpRequestFactory using the HttpClient - HttpComponentsClientHttpRequestFactory requestFactory = - new HttpComponentsClientHttpRequestFactory(httpClient); - - // Create a RestTemplate using the requestFactory - return new RestTemplate(requestFactory); - - - } - - private KeyStore keyStore(String file) throws Exception { - KeyStore keyStore = KeyStore.getInstance("PKCS12"); - File key = ResourceUtils.getFile(file); - try (InputStream in = new FileInputStream(key)) { - keyStore.load(in, keystorePassword.toCharArray()); - } - return keyStore; - } -} - - diff --git a/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/SampleApplication.java b/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/SampleApplication.java deleted file mode 100644 index 20274bd..0000000 --- a/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/SampleApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.jpmorgan.payments.sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class SampleApplication { - - public static void main(String[] args) { - SpringApplication.run(SampleApplication.class, args); - } - -} diff --git a/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/TrustAllManager.java b/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/TrustAllManager.java deleted file mode 100644 index bf70ea5..0000000 --- a/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/TrustAllManager.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.jpmorgan.payments.sample; - import java.security.cert.CertificateException; - import java.security.cert.X509Certificate; - import javax.net.ssl.X509TrustManager; - -public class TrustAllManager implements X509TrustManager { - - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - // Do nothing, to trust all client certificates without validation - } - - public void checkServerTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - // Do nothing, to trust all server certificates without validation - } - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - -} diff --git a/java/backend-example/ssl/src/main/resources/application.yml b/java/backend-example/ssl/src/main/resources/application.yml deleted file mode 100644 index ea23955..0000000 --- a/java/backend-example/ssl/src/main/resources/application.yml +++ /dev/null @@ -1,11 +0,0 @@ -server: - port : 4242 - -ssl: - keystore: - location: ${keystore_location} - password: ${keystore_password} -api: - globalPaymentsPath: /tsapi/v1/payments - cat: - url: https://apigatewaycat.jpmorgan.com \ No newline at end of file diff --git a/java/pom.xml b/java/pom.xml new file mode 100644 index 0000000..fe13321 --- /dev/null +++ b/java/pom.xml @@ -0,0 +1,107 @@ + + + + 4.0.0 + + com.jpmorgan.payments.digital_signature + digital_signature + 1.0-SNAPSHOT + + digital_signature + + + + UTF-8 + 12 + 12 + + + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + + + + javax.xml.bind + jaxb-api + 2.4.0-b180830.0359 + + + + org.json + json + 20231013 + + + org.junit.jupiter + junit-jupiter-engine + 5.2.0 + test + + + org.junit.platform + junit-platform-runner + 1.2.0 + test + + + + + + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-jar-plugin + 3.0.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + maven-site-plugin + 3.7.1 + + + maven-project-info-reports-plugin + 3.0.0 + + + + + diff --git a/java/sample-authentication-code-jdk-1.7/README.md b/java/sample-authentication-code-jdk-1.7/README.md deleted file mode 100644 index 43dbaa1..0000000 --- a/java/sample-authentication-code-jdk-1.7/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Access Token Generator -The purpose of this tool is to retrieve an access token using provided client details - -## Required Client Details - -The following values need to be updated in Constants.java: -* CLIENT_ID -* RESOURCE -* CERTIFICATE_FILE_PATH -* PRIVATE_KEY_FILE_PATH - - -## How To Run -Requirements: -* JDK 1.7 or newer -* Maven - -### Run in IDE -1. Update values in Constants.java -2. Run main() in TokenGeneratorApplication -3. Extract access token from console logs - -### Run Executable JAR -1. Update values in Constants.java -2. Use Maven to package JAR -3. From Command line: "java -jar [path to JAR]\token-generator-0.0.1-SNAPSHOT-jar-with-dependencies.jar" -4. Extract access token from console logs - - diff --git a/java/sample-authentication-code-jdk-1.7/pom.xml b/java/sample-authentication-code-jdk-1.7/pom.xml deleted file mode 100644 index fb87c7f..0000000 --- a/java/sample-authentication-code-jdk-1.7/pom.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - 4.0.0 - com.authentication - token-generator - 0.0.1-SNAPSHOT - token-generator - - - 1.7 - 1.7 - 1.7 - - - - - com.nimbusds - nimbus-jose-jwt - 9.37.2 - - - ch.qos.logback - logback-classic - 1.2.13 - - - org.slf4j - jcl-over-slf4j - 2.0.1 - - - org.projectlombok - lombok - 1.18.22 - provided - - - com.fasterxml.jackson.core - jackson-databind - 2.12.7.2 - - - commons-codec - commons-codec - 1.13 - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - package - - single - - - - - - com.authentication.example.TokenGeneratorApplication - - - - - jar-with-dependencies - - - - - - - - diff --git a/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/Constants.java b/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/Constants.java deleted file mode 100644 index bc8a8ac..0000000 --- a/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/Constants.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.authentication.example; - -/* - *************************************************************************** - * Constants needed for generating JWT and retrieving access token. * - *************************************************************************** - */ -public class Constants { - - public static final String ACCESS_TOKEN_URI = "https://idag2.jpmorganchase.com/adfs/oauth2/token"; - - // Provide certificate and client details - public static final String CLIENT_ID = "CC-000000-A000000-000000-PROD"; - - public static final String RESOURCE = "JPMC:URI:RS-000000-00000-Resource-PROD"; - - public static final String CERTIFICATE_FILE_PATH = "C:/certificate.crt"; - - public static final String PRIVATE_KEY_FILE_PATH = "C:/privateKey.key"; - - public static final long EXPIRES_IN = 300000L; - -} diff --git a/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/TokenGeneratorApplication.java b/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/TokenGeneratorApplication.java deleted file mode 100644 index 262ddad..0000000 --- a/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/TokenGeneratorApplication.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.authentication.example; - -import com.authentication.example.utilities.IdAnywhereUtility; -import com.authentication.example.utilities.JwtUtility; -import com.fasterxml.jackson.databind.JsonNode; -import org.apache.commons.codec.binary.Base64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.FileInputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.spec.PKCS8EncodedKeySpec; - -/* - ************************************************************************** - * Main executable class to retrieve access token * - ************************************************************************** - */ -public class TokenGeneratorApplication { - - private static final Logger LOG = LoggerFactory.getLogger("TokenGeneratorApplication"); - - public static void main(String[] args) { - - X509Certificate x509Certificate; - PrivateKey rsaKey; - - // Create x509 certificate from provided certificate file - LOG.info("Certificate file path: {}", Constants.CERTIFICATE_FILE_PATH); - try(FileInputStream certificateFile = new FileInputStream(Constants.CERTIFICATE_FILE_PATH)) { - CertificateFactory factory = CertificateFactory.getInstance("X509"); - x509Certificate = (X509Certificate) factory.generateCertificate(certificateFile); - LOG.info("Successfully generated certificate from file"); - } catch (Exception e) { - LOG.error("Error generating certificate from file", e); - return; - } - - // Create PrivateKey from provided key file - LOG.info("Private key file path: {}", Constants.PRIVATE_KEY_FILE_PATH); - try { - Path privateKeyPath = Paths.get(Constants.PRIVATE_KEY_FILE_PATH); - String key = new String(Files.readAllBytes(privateKeyPath)); - String privateKeyPEM = key - .replace("\n", "") - .replace("\r", "") - .replaceAll("-+BEGIN([A-Za-z\\s]+)KEY-+", "") - .replaceAll("-+END([A-Za-z\\s]+)KEY-+", ""); - byte[] decoded = Base64.decodeBase64(privateKeyPEM); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded); - rsaKey = keyFactory.generatePrivate(keySpec); - LOG.info("Successfully generated private key from file"); - } catch (Exception e) { - LOG.error("Error generating private key from file", e); - return; - } - - JsonNode idAnywhereResponse; - // Retrieve access token from IDAnywhere - try { - LOG.info("Attempting to retrieve access token from IDAnywhere"); - idAnywhereResponse = IdAnywhereUtility.getAccessToken(JwtUtility.getClientJwtAssertion(x509Certificate, rsaKey)); - } catch (Exception e) { - LOG.error("Error retrieving access token", e); - return; - } - - try { - LOG.info("Access Token: {}", idAnywhereResponse.get("access_token").asText()); - LOG.info("Expires In: {}", idAnywhereResponse.get("expires_in").asLong()); - LOG.info("Token Type: {}", idAnywhereResponse.get("token_type").asText()); - } catch (Exception e) { - LOG.error("Error while extracting IDA response: {}", idAnywhereResponse); - } - } - -} diff --git a/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/utilities/IdAnywhereUtility.java b/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/utilities/IdAnywhereUtility.java deleted file mode 100644 index 250be61..0000000 --- a/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/utilities/IdAnywhereUtility.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.authentication.example.utilities; - -import com.authentication.example.Constants; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.HttpsURLConnection; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.URL; - -/* - ************************************************************************** - * Utility to call IDAnywhere * - ************************************************************************** - */ -public class IdAnywhereUtility { - - private static final Logger LOG = LoggerFactory.getLogger("IdAnywhereUtility"); - - public static JsonNode getAccessToken(String jwt) throws Exception { - - String idaRequest = "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" - + "&client_assertion=" + jwt - + "&grant_type=client_credentials" - + "&client_id=" + Constants.CLIENT_ID - + "&resource=" + Constants.RESOURCE; - - try { - // Setup connection with IDAnywhere - URL idaUrl = new URL(Constants.ACCESS_TOKEN_URI); - HttpsURLConnection connection = (HttpsURLConnection) idaUrl.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - connection.setDoOutput(true); - connection.connect(); - - // Write IDAnywhere request to the output stream - OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream()); - wr.write(idaRequest); - wr.close(); - - // Read in response from IDAnywhere - InputStream in = connection.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - StringBuilder response = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - response.append(line); - } - - // Close the connection - connection.disconnect(); - - JsonNode jsonResponse = new ObjectMapper().readTree(response.toString()); - - if (jsonResponse != null) - return jsonResponse; - else - throw new Exception("Empty response returned from IDAnywhere"); - - } catch (Exception e) { - LOG.error("Error while sending request to IDAnywhere", e); - throw e; - } - } -} diff --git a/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/utilities/JwtUtility.java b/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/utilities/JwtUtility.java deleted file mode 100644 index 90e25bd..0000000 --- a/java/sample-authentication-code-jdk-1.7/src/main/java/com/authentication/example/utilities/JwtUtility.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.authentication.example.utilities; - -import com.authentication.example.Constants; -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSSigner; -import com.nimbusds.jose.crypto.RSASSASigner; -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.codec.digest.DigestUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.security.PrivateKey; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.util.Date; -import java.util.UUID; - -/* - ************************************************************************** - * Utility to create JWT * - ************************************************************************** - */ -public class JwtUtility { - - private static final Logger LOG = LoggerFactory.getLogger("JwtUtility"); - - public static String getClientJwtAssertion(Certificate certificate, PrivateKey privateKey) { - try { - Date now = new Date(); - SignedJWT signedJWT = new SignedJWT((new JWSHeader.Builder(JWSAlgorithm.RS256)).keyID(getThumbprint(certificate)).build(), - (new com.nimbusds.jwt.JWTClaimsSet.Builder()) - .jwtID(UUID.randomUUID().toString()) - .subject(Constants.CLIENT_ID) - .audience(Constants.ACCESS_TOKEN_URI) - .issuer(Constants.CLIENT_ID) - .issueTime(new Date()) - .expirationTime(new Date(now.getTime() + Constants.EXPIRES_IN)) - .build()); - JWSSigner rsaSigner = new RSASSASigner(privateKey); - signedJWT.sign(rsaSigner); - return signedJWT.serialize(); - } catch (JOSEException e) { - LOG.info("Unable to create a valid JWT Client Assertion.", e); - return null; - } - } - - private static String getThumbprint(Certificate certificate) { - try { - return DigestUtils.sha1Hex(certificate.getEncoded()).toUpperCase(); - } catch (CertificateEncodingException e) { - throw new RuntimeException("Error getting certificate thumbprint", e); - } - } -} diff --git a/java/sample-authentication-code-jdk-1.7/src/main/resources/logback.xml b/java/sample-authentication-code-jdk-1.7/src/main/resources/logback.xml deleted file mode 100644 index d52fbb7..0000000 --- a/java/sample-authentication-code-jdk-1.7/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} %highlight(%5.5(%level{5})) %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/java/sample-authentication-code/README.md b/java/sample-authentication-code/README.md deleted file mode 100644 index 28a59c9..0000000 --- a/java/sample-authentication-code/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Access Token Generator -The purpose of this tool is to retrieve an access token using provided client details - -## Required Client Details - -The following values need to be updated in Constants.java: -* CLIENT_ID -* RESOURCE -* CERTIFICATE_FILE_PATH -* PRIVATE_KEY_FILE_PATH - - -## How To Run -Requirements: -* JDK 11 or newer -* Maven - -### Run in IDE -1. Update values in Constants.java -2. Run main() in TokenGeneratorApplication -3. Extract access token from console logs - -### Run Executable JAR -1. Update values in Constants.java -2. Use Maven to package JAR -3. From Command line: "java -jar [path to JAR]\token-generator-0.0.1-SNAPSHOT-jar-with-dependencies.jar" -4. Extract access token from console logs - - diff --git a/java/sample-authentication-code/pom.xml b/java/sample-authentication-code/pom.xml deleted file mode 100644 index 48eb329..0000000 --- a/java/sample-authentication-code/pom.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - 4.0.0 - com.authentication - token-generator - 0.0.1-SNAPSHOT - token-generator - - - 11 - 11 - 11 - - - - - com.nimbusds - nimbus-jose-jwt - 9.40 - - - ch.qos.logback - logback-classic - 1.5.6 - - - org.slf4j - jcl-over-slf4j - 2.0.7 - - - org.projectlombok - lombok - 1.18.22 - provided - - - com.fasterxml.jackson.core - jackson-databind - 2.17.1 - - - commons-codec - commons-codec - 1.17.0 - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - - - package - - single - - - - - - com.authentication.example.TokenGeneratorApplication - - - - - jar-with-dependencies - - - - - - - - diff --git a/java/sample-authentication-code/src/main/java/com/authentication/example/Constants.java b/java/sample-authentication-code/src/main/java/com/authentication/example/Constants.java deleted file mode 100644 index f26e1d5..0000000 --- a/java/sample-authentication-code/src/main/java/com/authentication/example/Constants.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.authentication.example; - -/* - *************************************************************************** - * Constants needed for generating JWT and retrieving access token. * - *************************************************************************** - */ -public class Constants { - - public static final String ACCESS_TOKEN_URI = "https://idag2.jpmorganchase.com/adfs/oauth2/token"; - - // Provide certificate and client details - public static final String CLIENT_ID = "CC-000000-A000000-000000-PROD"; - - public static final String RESOURCE = "JPMC:URI:RS-000000-00000-Resource-PROD"; - - public static final String CERTIFICATE_FILE_PATH = "C:/certificate.crt"; - - public static final String PRIVATE_KEY_FILE_PATH = "C:/privateKey.key"; - - public static final long EXPIRES_IN = 300000L; - -} diff --git a/java/sample-authentication-code/src/main/java/com/authentication/example/TokenGeneratorApplication.java b/java/sample-authentication-code/src/main/java/com/authentication/example/TokenGeneratorApplication.java deleted file mode 100644 index fc9da47..0000000 --- a/java/sample-authentication-code/src/main/java/com/authentication/example/TokenGeneratorApplication.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.authentication.example; - -import com.authentication.example.utilities.IdAnywhereUtility; -import com.authentication.example.utilities.JwtUtility; -import com.fasterxml.jackson.databind.JsonNode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.FileInputStream; -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.spec.PKCS8EncodedKeySpec; -import java.util.Base64; - -/* - ************************************************************************** - * Main executable class to retrieve access token * - ************************************************************************** - */ -public class TokenGeneratorApplication { - - private static final Logger LOG = LoggerFactory.getLogger("TokenGeneratorApplication"); - - public static void main(String[] args) { - - X509Certificate x509Certificate; - PrivateKey rsaKey; - - // Create x509 certificate from provided certificate file - LOG.info("Certificate file path: {}", Constants.CERTIFICATE_FILE_PATH); - try(FileInputStream certificateFile = new FileInputStream(Constants.CERTIFICATE_FILE_PATH)) { - CertificateFactory factory = CertificateFactory.getInstance("X509"); - x509Certificate = (X509Certificate) factory.generateCertificate(certificateFile); - LOG.info("Successfully generated certificate from file"); - } catch (Exception e) { - LOG.error("Error generating certificate from file", e); - return; - } - - // Create PrivateKey from provided key file - LOG.info("Private key file path: {}", Constants.PRIVATE_KEY_FILE_PATH); - try(FileInputStream privateKeyFile = new FileInputStream(Constants.PRIVATE_KEY_FILE_PATH)) { - String key = new String(privateKeyFile.readAllBytes()); - String privateKeyPEM = key - .replace("\n", "") - .replace("\r", "") - .replaceAll("-+BEGIN([A-Za-z\\s]+)KEY-+", "") - .replaceAll("-+END([A-Za-z\\s]+)KEY-+", ""); - byte[] decoded = Base64.getDecoder().decode(privateKeyPEM); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded); - rsaKey = keyFactory.generatePrivate(keySpec); - LOG.info("Successfully generated private key from file"); - } catch (Exception e) { - LOG.error("Error generating private key from file", e); - return; - } - - JsonNode idAnywhereResponse; - // Retrieve access token from IDAnywhere - try { - LOG.info("Attempting to retrieve access token from IDAnywhere"); - idAnywhereResponse = IdAnywhereUtility.getAccessToken(JwtUtility.getClientJwtAssertion(x509Certificate, rsaKey)); - } catch (Exception e) { - LOG.error("Error retrieving access token", e); - return; - } - - try { - LOG.info("Access Token: {}", idAnywhereResponse.get("access_token").asText()); - LOG.info("Expires In: {}", idAnywhereResponse.get("expires_in").asLong()); - LOG.info("Token Type: {}", idAnywhereResponse.get("token_type").asText()); - } catch (Exception e) { - LOG.error("Error while extracting IDA response: {}", idAnywhereResponse); - } - } - -} diff --git a/java/sample-authentication-code/src/main/java/com/authentication/example/utilities/IdAnywhereUtility.java b/java/sample-authentication-code/src/main/java/com/authentication/example/utilities/IdAnywhereUtility.java deleted file mode 100644 index 635db5b..0000000 --- a/java/sample-authentication-code/src/main/java/com/authentication/example/utilities/IdAnywhereUtility.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.authentication.example.utilities; - -import com.authentication.example.Constants; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.HttpsURLConnection; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.net.URL; - -/* - ************************************************************************** - * Utility to call IDAnywhere * - ************************************************************************** - */ -public class IdAnywhereUtility { - - private static final Logger LOG = LoggerFactory.getLogger("IdAnywhereUtility"); - - public static JsonNode getAccessToken(String jwt) throws Exception { - String idaRequest = "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" - + "&client_assertion=" + jwt - + "&grant_type=client_credentials" - + "&client_id=" + Constants.CLIENT_ID - + "&resource=" + Constants.RESOURCE; - - try { - // Setup connection with IDAnywhere - URL idaUrl = new URL(Constants.ACCESS_TOKEN_URI); - HttpsURLConnection connection = (HttpsURLConnection) idaUrl.openConnection(); - connection.setRequestMethod("POST"); - connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - connection.setDoOutput(true); - connection.connect(); - - // Write IDAnywhere request to the output stream - OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream()); - wr.write(idaRequest); - wr.close(); - - // Read in response from IDAnywhere - InputStream in = connection.getInputStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - StringBuilder response = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - response.append(line); - } - - // Close the connection - connection.disconnect(); - - JsonNode jsonResponse = new ObjectMapper().readTree(response.toString()); - - if (jsonResponse != null) - return jsonResponse; - else - throw new Exception("Empty response returned from IDAnywhere"); - } catch(Exception e) { - LOG.error("Error while sending request to IDAnywhere", e); - throw e; - } - } -} diff --git a/java/sample-authentication-code/src/main/java/com/authentication/example/utilities/JwtUtility.java b/java/sample-authentication-code/src/main/java/com/authentication/example/utilities/JwtUtility.java deleted file mode 100644 index a357f56..0000000 --- a/java/sample-authentication-code/src/main/java/com/authentication/example/utilities/JwtUtility.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.authentication.example.utilities; - -import com.authentication.example.Constants; -import com.nimbusds.jose.JOSEException; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.JWSHeader; -import com.nimbusds.jose.JWSSigner; -import com.nimbusds.jose.JWSSignerOption; -import com.nimbusds.jose.crypto.RSASSASigner; -import com.nimbusds.jose.crypto.opts.AllowWeakRSAKey; -import com.nimbusds.jwt.SignedJWT; -import org.apache.commons.codec.digest.DigestUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.security.PrivateKey; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.util.Collections; -import java.util.Date; -import java.util.Set; -import java.util.UUID; - -/* - ************************************************************************** - * Utility to create JWT * - ************************************************************************** - */ -public class JwtUtility { - - private static final Logger LOG = LoggerFactory.getLogger("JwtUtility"); - - public static String getClientJwtAssertion(Certificate certificate, PrivateKey privateKey) { - try { - Date now = new Date(); - SignedJWT signedJWT = new SignedJWT( - (new JWSHeader.Builder(JWSAlgorithm.RS256)).keyID(getThumbprint(certificate)).build(), - (new com.nimbusds.jwt.JWTClaimsSet.Builder()) - .jwtID(UUID.randomUUID().toString()) - .subject(Constants.CLIENT_ID) - .audience(Constants.ACCESS_TOKEN_URI) - .issuer(Constants.CLIENT_ID) - .issueTime(new Date()) - .expirationTime(new Date(now.getTime() + Constants.EXPIRES_IN)) - .build()); - Set options = Collections.singleton(AllowWeakRSAKey.getInstance()); - JWSSigner rsaSigner = new RSASSASigner(privateKey, options); - signedJWT.sign(rsaSigner); - return signedJWT.serialize(); - } catch (JOSEException e) { - LOG.info("Unable to create a valid JWT Client Assertion.", e); - return null; - } - } - - private static String getThumbprint(Certificate certificate) { - try { - return DigestUtils.sha1Hex(certificate.getEncoded()).toUpperCase(); - } catch (CertificateEncodingException e) { - throw new RuntimeException("Error getting certificate thumbprint", e); - } - } -} diff --git a/java/sample-authentication-code/src/main/resources/logback.xml b/java/sample-authentication-code/src/main/resources/logback.xml deleted file mode 100644 index 01fd2d4..0000000 --- a/java/sample-authentication-code/src/main/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} %highlight(%5.5(%level{5})) %logger{36} - %msg%n - - - - - - - - \ No newline at end of file diff --git a/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/DigitalSignatureGenerator.java b/java/src/main/java/com/jpmorgan/payments/digital_signature/JWTDemo.java similarity index 50% rename from java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/DigitalSignatureGenerator.java rename to java/src/main/java/com/jpmorgan/payments/digital_signature/JWTDemo.java index 967af29..64663b5 100644 --- a/java/backend-example/ssl/src/main/java/com/jpmorgan/payments/sample/DigitalSignatureGenerator.java +++ b/java/src/main/java/com/jpmorgan/payments/digital_signature/JWTDemo.java @@ -1,26 +1,18 @@ -package com.jpmorgan.payments.sample; +package com.jpmorgan.payments.digital_signature; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; -import org.json.JSONObject; -import org.springframework.stereotype.Service; - import javax.xml.bind.DatatypeConverter; +import org.json.JSONObject; -@Service -public class DigitalSignatureGenerator +public class JWTDemo { - String privateKeyFilename = "./src/main/resources/static/private.key"; private static String formatKeyString(String key) { return key.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "") @@ -29,58 +21,47 @@ private static String formatKeyString(String key) { /** * Method for reading in a private key and preparing it for signing - * + * + * @param key Your digital signature key that has been configured in + * developer.jpmorgan.com * @return a Private Key object */ - private PrivateKey gatherPrivateKey() { - byte[] keyBytes = readCertFile(privateKeyFilename); - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + private static PrivateKey gatherPrivateKey(String key) { + byte[] prvKeyBytes = DatatypeConverter.parseBase64Binary(formatKeyString(key)); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(prvKeyBytes); PrivateKey prvKey = null; try { KeyFactory kf = KeyFactory.getInstance("RSA"); prvKey = kf.generatePrivate(keySpec); - } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { + } catch (InvalidKeySpecException e) { // TODO Proper error handling is required here e.printStackTrace(); - } - return prvKey; - } - - private byte[] readCertFile(String filename) { - try { - String key = Files.readString(Paths.get(filename)); - return DatatypeConverter.parseBase64Binary(formatKeyString(key)); - } catch (IOException e) { + } catch (NoSuchAlgorithmException e) { + // TODO Proper error handling is required here e.printStackTrace(); } - } - - private JSONObject formatPaymentAmountField(String payload) { - final JSONObject payloadObj = new JSONObject(payload); - JSONObject payments = payloadObj.getJSONObject("payments"); - String amount = payments.getString("paymentAmount"); - payments.put("paymentAmount", Double.parseDouble(amount)); - payloadObj.put("payments", payments); - return payloadObj; + return prvKey; } /** * Method for signing a JSON payload - * + * * @param payload The JSON payload to be digitally signed. + * @param key Your digital signature key that has been configured in + * developer.jpmorgan.com * @return */ - public String createJWT(String payload) { + public static String createJWT(String payload, String key) { // The JWT signature algorithm we will be using to sign the token SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.RS256; // Prepare your private key for signing - PrivateKey prvKey = gatherPrivateKey(); - JSONObject payments = formatPaymentAmountField(payload); + PrivateKey prvKey = gatherPrivateKey(key); + final JSONObject obj = new JSONObject(payload); - return Jwts.builder().setClaims(payments.toMap()) + return Jwts.builder().setClaims(obj.toMap()) .signWith(prvKey, signatureAlgorithm).compact(); } diff --git a/java/src/test/java/com/jpmorgan/payments/digital_signature/JWTTest.java b/java/src/test/java/com/jpmorgan/payments/digital_signature/JWTTest.java new file mode 100644 index 0000000..f348364 --- /dev/null +++ b/java/src/test/java/com/jpmorgan/payments/digital_signature/JWTTest.java @@ -0,0 +1,55 @@ +package com.jpmorgan.payments.digital_signature; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; +import java.util.Map; + +import org.json.JSONObject; +import org.junit.jupiter.api.Test; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jws; +import io.jsonwebtoken.Jwts; + +public class JWTTest + +{ + + Map env = System.getenv(); + String privateKey = env.get("PRIVATE"); + String publicKey = env.get("PUBLIC"); + String payload = "{\"user_id\":123}"; + + PublicKey formatPublicKey(String key) { + String formattedKey = key.replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "").replace("\\n", "").replaceAll("\\s+", ""); + + X509EncodedKeySpec keySpecX509 = new X509EncodedKeySpec(Base64.getDecoder().decode(formattedKey)); + PublicKey publicKey = null; + KeyFactory kf; + try { + kf = KeyFactory.getInstance("RSA"); + publicKey = kf.generatePublic(keySpecX509); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return publicKey; + } + + @Test + void assertSignatureCreated() { + String result = JWTDemo.createJWT(payload, privateKey); + + PublicKey pKey = formatPublicKey(publicKey); + Jws jws = Jwts.parserBuilder().setSigningKey(pKey).build().parseClaimsJws(result); + JSONObject obj = new JSONObject(jws.getBody()); + assertEquals(payload, obj.toString()); + } +} diff --git a/js/README.md b/js/README.md new file mode 100644 index 0000000..d68063e --- /dev/null +++ b/js/README.md @@ -0,0 +1,28 @@ +# Digital Signature JS snippet + +A snippet of JS code to show how to create a digital signature + +## Requirements + +- yarn installed +- [Configured .env file](../README.md) + +## How to run + +You can run this code by running the tests or by including it in your codebase. + +1. Confirm `.env` configuration + +Ensure the certificate keys are configured in `.env` in this directory. You can find information on generating certificates at in our [readme](../README.md). It should include the following keys: + +```yaml +PRIVATE=... +PUBLIC= +``` + +2. Install dependencies and start the server + +``` +yarn install +yarn test +``` diff --git a/js/backend-example/.env.example b/js/backend-example/.env.example deleted file mode 100644 index 3e1fd47..0000000 --- a/js/backend-example/.env.example +++ /dev/null @@ -1,12 +0,0 @@ -## SSL Details -ENDPOINT_URL="https://apigatewaycat.jpmorgan.com" -CERT="" -KEY="" -DIGITAL="" - -## OAuth Details -DIGITAL="" -ENDPOINT_URL="https://api-mock.payments.jpmorgan.com" -ACCESS_TOKEN_URL="https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token" -ACCESS_TOKEN_USERNAME="" -ACCESS_TOKEN_SECRET="" \ No newline at end of file diff --git a/js/backend-example/README.md b/js/backend-example/README.md deleted file mode 100644 index 9518b46..0000000 --- a/js/backend-example/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# NODE JS Backend Samples - -In this folder there are two code samples for connecting to our APIs using node js. -Each sample is categorised by the authentication method you will use. - -** Note this is not production code and is supplied to get developers started ** - -## Requirements - -- Node v18+ -- Configured .env file - -## How to run - OAuth - -1. Configure a '.env' file in the repository by adding your CLIENT_ID and CLIENT_SECRET, directions can be followed here: [https://developer.payments.jpmorgan.com/quick-start#add-an-api-to-your-project](https://developer.payments.jpmorgan.com/quick-start#add-an-api-to-your-project) (** this file should not be committed**) - -2. Install dependencies and start the server - -``` -yarn install -yarn start -``` - -3. Import the postman collection at the top of this repo to test out the server connection, you can use folder 'backend-examples'. Instructions for importing postman collections can be found ([here](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)) - -## How to run - SSL - -1. Configure a '.env' file in the repository by adding your SSL Certificate and Key to the file (** this file should not be committed**). You can copy the layout in .env.example. To upload your certificates you will need to onboard to [https://developer.jpmorgan.com](https://developer.jpmorgan.com) -2. Install dependencies and start the server - -``` -yarn install -yarn start -``` - -3. Import the postman collection at the top of this repo to test out the server connection, you can use folder 'backend-examples'. Instructions for importing postman collections can be found ([here](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)) diff --git a/js/backend-example/oauth/index.js b/js/backend-example/oauth/index.js deleted file mode 100644 index ebbd090..0000000 --- a/js/backend-example/oauth/index.js +++ /dev/null @@ -1,140 +0,0 @@ -/** - * This code sets up an Express server that acts as a proxy for forwarding requests to an API server. - * It includes functionality to modify request bodies, handle proxy responses, and handle requests with digital signatures and access tokens. - * Within this code JWT is same as digital signature. - */ - -// Import required modules -const jwt = require("jsonwebtoken"); // For JSON Web Tokens -const express = require("express"); // Express framework for creating the server -const { - createProxyMiddleware, - responseInterceptor, -} = require("http-proxy-middleware"); // For creating proxy middleware -const { gatherAccessToken } = require("./oAuthHandler"); // Custom module for gathering access token -require("dotenv").config(); // For loading environment variables - -// Create an Express application -const app = express(); - -// Middleware to parse JSON and URL-encoded request bodies -app.use(express.json()); -app.use(express.urlencoded({ extended: true })); - -// Load endpoint URL and digital signature key from environment variables -const endpointUrl = process.env.ENDPOINT_URL; -const digitalSignatureKey = process.env.DIGITAL; - -// Function to add logging to proxy responses -const handleProxyResponse = async (responseBuffer, proxyRes, req) => { - const exchange = `[${req.method}] [${proxyRes.statusCode}] ${req.path} -> ${proxyRes.req.protocol}//${proxyRes.req.host}${proxyRes.req.path}`; - console.log(exchange); - if (proxyRes.headers["content-type"] === "application/json") { - const data = JSON.parse(responseBuffer.toString("utf8")); - return JSON.stringify(data); - } - return responseBuffer; -}; - -// Function to create proxy middleware configuration with access token -async function createProxyConfiguration(target, accessToken) { - const options = { - target, - changeOrigin: true, - selfHandleResponse: true, - onProxyReq: async (proxyReq, req) => { - proxyReq.setHeader("Authorization", `bearer ${accessToken}`); - if ( - req.body && - req.method === "POST" && - req.path.includes("/tsapi/v1/payments") - ) { - const bodyData = JSON.stringify(req.body); - proxyReq.setHeader("Content-Type", "application/json"); - proxyReq.setHeader("Content-Length", Buffer.byteLength(bodyData)); - proxyReq.write(bodyData); - proxyReq.end(); - } - }, - onProxyRes: responseInterceptor(handleProxyResponse), - }; - return createProxyMiddleware(options); -} - -// Function to create proxy middleware configuration with digital signature and access token -async function createProxyConfigurationForDigital( - target, - digitalSignature, - accessToken -) { - const options = { - target, - changeOrigin: true, - selfHandleResponse: true, - pathRewrite: { - "^/digitalSignature": "", - }, - onProxyReq: async (proxyReq, req) => { - proxyReq.setHeader("Authorization", `bearer ${accessToken}`); - if (req.body) { - proxyReq.setHeader("Content-Type", "text/xml"); - proxyReq.setHeader( - "Content-Length", - Buffer.byteLength(digitalSignature) - ); - proxyReq.write(digitalSignature); - } - }, - onProxyRes: responseInterceptor(handleProxyResponse), - onError: (err) => { - console.error(err); - }, - }; - return createProxyMiddleware(options); -} - -// Function to generate a digital signature using JWT -function generateDigitalSignature(digital_key, body) { - return jwt.sign(body, digital_key, { algorithm: "RS256" }); -} - -// Middleware to handle requests with a digital signature -app.use("/digitalSignature/*", async (req, res, next) => { - // Fix for some languages sending payment amount as a string - if (req.body?.payments?.paymentAmount) { - req.body.payments.paymentAmount = parseInt(req.body.payments.paymentAmount); - } - - // Retrieve access token - const accessToken = await gatherAccessToken(); - - // Generate digital signature - const digitalSignatureTest = generateDigitalSignature( - digitalSignatureKey, - req.body - ); - - // Create proxy configuration with digital signature and access token - const func = await createProxyConfigurationForDigital( - endpointUrl, - digitalSignatureTest, - accessToken - ); - func(req, res, next); -}); - -// Middleware to handle other requests -app.use("/*", async (req, res, next) => { - // Retrieve access token - const accessToken = await gatherAccessToken(); - if (accessToken) { - // Create proxy configuration with access token - const func = await createProxyConfiguration(endpointUrl, accessToken); - func(req, res, next); - } -}); - -// Start the server on port 4242 -app.listen(4242, () => - console.log(`Node server listening at http://localhost:4242`) -); diff --git a/js/backend-example/oauth/oAuthHandler.js b/js/backend-example/oauth/oAuthHandler.js deleted file mode 100644 index 4406fac..0000000 --- a/js/backend-example/oauth/oAuthHandler.js +++ /dev/null @@ -1,32 +0,0 @@ -const axios = require("axios"); -const qs = require("qs"); - -require("dotenv").config(); - -const { ACCESS_TOKEN_URL, ACCESS_TOKEN_USERNAME, ACCESS_TOKEN_SECRET } = - process.env; -const scope = "jpm:payments:sandbox"; - -const authString = Buffer.from( - `${ACCESS_TOKEN_USERNAME}:${ACCESS_TOKEN_SECRET}` -).toString("base64"); -const data = "grant_type=client_credentials&scope=" + encodeURIComponent(scope); - -const gatherAccessToken = () => - axios - .post(ACCESS_TOKEN_URL, data, { - headers: { - Authorization: `Basic ${authString}`, - "Content-Type": "application/x-www-form-urlencoded", - }, - }) - .then((response) => { - // Handle successful response - return response.data.access_token; - }) - .catch((error) => { - // Handle error - console.error("Error fetching access token:", error.message); - }); - -module.exports = { gatherAccessToken }; diff --git a/js/backend-example/oauth/package.json b/js/backend-example/oauth/package.json deleted file mode 100644 index d0a0b69..0000000 --- a/js/backend-example/oauth/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "node-js-oauth-example", - "version": "1.0.0", - "description": "JP Morgan Payments node js example", - "main": "index.js", - "scripts": { - "start": "node index.js", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "jp morgan payments", - "license": "ISC", - "dependencies": { - "axios": "^1.6.5", - "dotenv": "^16.0.3", - "express": "^4.19.2", - "http-proxy-middleware": "^2.0.6", - "jsonwebtoken": "^9.0.2", - "qs": "^6.11.2" - } -} diff --git a/js/backend-example/oauth/yarn.lock b/js/backend-example/oauth/yarn.lock deleted file mode 100644 index f5ec285..0000000 --- a/js/backend-example/oauth/yarn.lock +++ /dev/null @@ -1,707 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@types/http-proxy@^1.17.8": - version "1.17.14" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" - integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== - dependencies: - "@types/node" "*" - -"@types/node@*": - version "20.11.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.5.tgz#be10c622ca7fcaa3cf226cf80166abc31389d86e" - integrity sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w== - dependencies: - undici-types "~5.26.4" - -accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -axios@^1.6.5: - version "1.6.5" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.5.tgz#2c090da14aeeab3770ad30c3a1461bc970fb0cd8" - integrity sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg== - dependencies: - follow-redirects "^1.15.4" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -body-parser@1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - -braces@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== - dependencies: - function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4, content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== - dependencies: - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -dotenv@^16.0.3: - version "16.3.2" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.2.tgz#3cb611ce5a63002dbabf7c281bc331f69d28f03f" - integrity sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ== - -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -express@^4.19.2: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.6.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -follow-redirects@^1.0.0, follow-redirects@^1.15.4: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== - dependencies: - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-proxy-middleware@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== - dependencies: - "@types/http-proxy" "^1.17.8" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -inherits@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-glob@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -jsonwebtoken@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" - integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== - dependencies: - jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^7.5.4" - -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== - -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== - -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -micromatch@^4.0.2: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -object-inspect@^1.9.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -proxy-from-env@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" - integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -qs@^6.11.2: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -safe-buffer@5.2.1, safe-buffer@^5.0.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -semver@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -set-function-length@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" - integrity sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w== - dependencies: - define-data-property "^1.1.1" - function-bind "^1.1.2" - get-intrinsic "^1.2.2" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/js/backend-example/ssl/package.json b/js/backend-example/ssl/package.json deleted file mode 100644 index 3aadf15..0000000 --- a/js/backend-example/ssl/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "node-js-ssl-example", - "version": "1.0.0", - "description": "JP Morgan Payments node js example", - "main": "server.js", - "scripts": { - "start": "node server.js", - "test": "jest server.test.js" - }, - "author": "jp morgan payments", - "license": "ISC", - "dependencies": { - "dotenv": "^16.0.3", - "express": "^4.19.2", - "http-proxy-middleware": "^2.0.6", - "https": "^1.0.0", - "jsonwebtoken": "^9.0.2" - }, - "devDependencies": { - "jest": "^29.7.0", - "supertest": "^6.3.4" - } -} diff --git a/js/backend-example/ssl/server.js b/js/backend-example/ssl/server.js deleted file mode 100644 index b4c8a09..0000000 --- a/js/backend-example/ssl/server.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * This code is a Node.js application that acts as a proxy server, forwarding requests to an API server. - * It includes functionality to modify request bodies, handle proxy responses, and create digital signatures for certain requests. - * Within this code JWT is same as digital signature. - * - */ -// Import required modules -const jwt = require("jsonwebtoken"); // For JSON Web Tokens -const express = require("express"); // Express framework for creating the server -const https = require("https"); // For making HTTPS requests -const { - createProxyMiddleware, - responseInterceptor, -} = require("http-proxy-middleware"); // For creating proxy middleware -require("dotenv").config(); // For loading environment variables - -// Create an Express application -const app = express(); - -// Middleware to parse JSON and URL-encoded request bodies -app.use(express.json()); -app.use(express.urlencoded({ extended: true })); - -// Load SSL key and certificate from environment variables -const httpsOptions = { - key: process.env.KEY, - cert: process.env.CERT, -}; - -// Load endpoint URL and digital signature key from environment variables -const endpointUrl = process.env.ENDPOINT_URL; -const digitalSignatureKey = process.env.DIGITAL; - -// Function to modify the request body before proxying -var restream = function (proxyReq, req, res, options) { - if (req.body) { - let bodyData = JSON.stringify(req.body); - proxyReq.setHeader("Content-Type", "application/json"); - proxyReq.setHeader("Content-Length", Buffer.byteLength(bodyData)); - proxyReq.write(bodyData); - } -}; - -// Function to add logging to proxy responses -const handleProxyResponse = async (responseBuffer, proxyRes, req) => { - const exchange = `[${req.method}] [${proxyRes.statusCode}] ${req.path} -> ${proxyRes.req.protocol}//${proxyRes.req.host}${proxyRes.req.path}`; - console.log(exchange); - if (proxyRes.headers["content-type"] === "application/json") { - const data = JSON.parse(responseBuffer.toString("utf8")); - return JSON.stringify(data); - } - return responseBuffer; -}; - -// Function to create proxy middleware configuration -async function createProxyConfiguration(target) { - const options = { - target, - changeOrigin: true, - selfHandleResponse: true, - agent: new https.Agent(httpsOptions), - onProxyReq: restream, - onProxyRes: responseInterceptor(handleProxyResponse), - onError: (err) => { - console.error(err); - }, - }; - return createProxyMiddleware(options); -} - -// Function to create proxy middleware configuration with digital signature -async function createProxyConfigurationForDigital(target, digitalSignature) { - const options = { - target, - changeOrigin: true, - selfHandleResponse: true, - agent: new https.Agent(httpsOptions), - pathRewrite: { - "^/digitalSignature": "", - }, - onProxyReq: async (proxyReq, req) => { - if (req.body) { - // When sending a digital signature request content needs to be text/xml to be accepted - proxyReq.setHeader("Content-Type", "text/xml"); - proxyReq.setHeader( - "Content-Length", - Buffer.byteLength(digitalSignature) - ); - proxyReq.write(digitalSignature); - } - }, - onProxyRes: responseInterceptor(handleProxyResponse), - onError: (err) => { - console.error(err); - }, - }; - return createProxyMiddleware(options); -} - -// Function to generate a digital signature using JWT -function generateDigitalSignature(digital_key, body) { - return jwt.sign(body, digital_key, { algorithm: "RS256" }); -} - -// Middleware to handle requests with a digital signature -app.use("/digitalSignature/*", async (req, res, next) => { - if (req.body?.payments?.paymentAmount) { - req.body.payments.paymentAmount = parseInt(req.body.payments.paymentAmount); - } - const digitalSignatureTest = generateDigitalSignature( - digitalSignatureKey, - req.body - ); - const func = await createProxyConfigurationForDigital( - endpointUrl, - digitalSignatureTest - ); - func(req, res, next); -}); - -// Middleware to handle other requests -app.use("/*", async (req, res, next) => { - const func = await createProxyConfiguration(endpointUrl); - func(req, res, next); -}); - -// Start the server on port 4242 -const server = app.listen(4242, () => - console.log(`Node server listening at http://localhost:4242`) -); - -// Export the server for testing or other purposes -module.exports = server; diff --git a/js/backend-example/ssl/server.test.js b/js/backend-example/ssl/server.test.js deleted file mode 100644 index d481474..0000000 --- a/js/backend-example/ssl/server.test.js +++ /dev/null @@ -1,79 +0,0 @@ -const supertest = require("supertest"); -const server = require("./server"); -const requestWithSupertest = supertest(server); - -describe("Express App Tests", () => { - it("GET /transactions should return transactions", async () => { - const res = await requestWithSupertest.get( - "/tsapi/v2/transactions?relativeDateType=CURRENT_DAY&accountIds=000000010975001,000000011008182,000000010975514,000000010975001,000000010900009" - ); - expect(res.status).toEqual(200); - expect(res.type).toEqual(expect.stringContaining("json")); - }); - it("POST /balances should return balances", async () => { - const res = await requestWithSupertest.post("/accessapi/balance").send({ - accountList: [ - { - accountId: "000000010962009", - }, - { - accountId: "000000011153244", - }, - { - accountId: "000000010962009", - }, - { - accountId: "000000010900009", - }, - { - accountId: "000000011315421", - }, - ], - }); - expect(res.status).toEqual(200); - expect(res.type).toEqual(expect.stringContaining("json")); - }); - it("GET /payments should return a new payment", async () => { - const res = await requestWithSupertest - .post("/digitalSignature/tsapi/v1/payments") - .send({ - payments: { - requestedExecutionDate: "2023-09-04", - paymentAmount: 25, - paymentType: "RTP", - paymentIdentifiers: { - endToEndId: "uf16938248603981123", - }, - paymentCurrency: "EUR", - transferType: "CREDIT", - debtor: { - debtorName: "OBGLRTPCL1 Account", - debtorAccount: { - accountId: "DE88501108006231400596", - accountCurrency: "EUR", - accountType: "IBAN", - }, - }, - debtorAgent: { - financialInstitutionId: { - bic: "CHASDEFX", - }, - }, - creditor: { - creditorName: "UNICORNUAT Account", - creditorAccount: { - accountId: "DE45501108000041287103", - accountCurrency: "EUR", - }, - }, - creditorAgent: { - financialInstitutionId: { - bic: "CHASDEFX", - }, - }, - }, - }); - expect(res.status).toEqual(200); - expect(res.type).toEqual(expect.stringContaining("json")); - }); -}); diff --git a/js/backend-example/ssl/yarn.lock b/js/backend-example/ssl/yarn.lock deleted file mode 100644 index 084b024..0000000 --- a/js/backend-example/ssl/yarn.lock +++ /dev/null @@ -1,2826 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== - dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" - integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== - dependencies: - "@babel/highlight" "^7.23.4" - chalk "^2.4.2" - -"@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== - -"@babel/core@^7.11.6", "@babel/core@^7.12.3": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.7.tgz#4d8016e06a14b5f92530a13ed0561730b5c6483f" - integrity sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.7" - "@babel/parser" "^7.23.6" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/generator@^7.23.6", "@babel/generator@^7.7.2": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== - dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/helper-compilation-targets@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" - integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== - dependencies: - "@babel/compat-data" "^7.23.5" - "@babel/helper-validator-option" "^7.23.5" - browserslist "^4.22.2" - lru-cache "^5.1.1" - semver "^6.3.1" - -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== - dependencies: - "@babel/types" "^7.22.15" - -"@babel/helper-module-transforms@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" - integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== - dependencies: - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-simple-access" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/helper-validator-identifier" "^7.22.20" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" - integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== - -"@babel/helper-simple-access@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" - integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-split-export-declaration@^7.22.6": - version "7.22.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" - integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-string-parser@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-validator-identifier@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" - integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== - -"@babel/helper-validator-option@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" - integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== - -"@babel/helpers@^7.23.7": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.8.tgz#fc6b2d65b16847fd50adddbd4232c76378959e34" - integrity sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ== - dependencies: - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.7" - "@babel/types" "^7.23.6" - -"@babel/highlight@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" - integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" - integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== - -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/template@^7.22.15", "@babel/template@^7.3.3": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.15.tgz#09576efc3830f0430f4548ef971dde1350ef2f38" - integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/parser" "^7.22.15" - "@babel/types" "^7.22.15" - -"@babel/traverse@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.7.tgz#9a7bf285c928cb99b5ead19c3b1ce5b310c9c305" - integrity sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.6" - "@babel/types" "^7.23.6" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.3.3": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" - integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== - dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - -"@jest/core@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== - dependencies: - "@jest/console" "^29.7.0" - "@jest/reporters" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.7.0" - jest-config "^29.7.0" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-resolve-dependencies "^29.7.0" - jest-runner "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - jest-watcher "^29.7.0" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== - dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - -"@jest/expect-utils@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== - dependencies: - jest-get-type "^29.6.3" - -"@jest/expect@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== - dependencies: - expect "^29.7.0" - jest-snapshot "^29.7.0" - -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== - dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -"@jest/globals@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/types" "^29.6.3" - jest-mock "^29.7.0" - -"@jest/reporters@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^6.0.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - jest-worker "^29.7.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - -"@jest/schemas@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" - integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== - dependencies: - "@sinclair/typebox" "^0.27.8" - -"@jest/source-map@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== - dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== - dependencies: - "@jest/console" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== - dependencies: - "@jest/test-result" "^29.7.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - slash "^3.0.0" - -"@jest/transform@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== - dependencies: - "@jridgewell/set-array" "^1.0.1" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - -"@jridgewell/resolve-uri@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" - integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== - -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== - -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.22" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" - integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - -"@sinclair/typebox@^0.27.8": - version "0.27.8" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" - integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== - -"@sinonjs/commons@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - -"@types/babel__core@^7.1.14": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" - integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== - dependencies: - "@babel/types" "^7.20.7" - -"@types/graceful-fs@^4.1.3": - version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" - integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== - dependencies: - "@types/node" "*" - -"@types/http-proxy@^1.17.8": - version "1.17.14" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.14.tgz#57f8ccaa1c1c3780644f8a94f9c6b5000b5e2eec" - integrity sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/node@*": - version "20.11.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.5.tgz#be10c622ca7fcaa3cf226cf80166abc31389d86e" - integrity sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w== - dependencies: - undici-types "~5.26.4" - -"@types/stack-utils@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== - dependencies: - "@types/yargs-parser" "*" - -accepts@~1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - -ansi-regex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" - integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" - integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== - -anymatch@^3.0.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== - -asap@^2.0.0: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -babel-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== - dependencies: - "@jest/transform" "^29.7.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.6.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== - dependencies: - babel-plugin-jest-hoist "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -body-parser@1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" - integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== - dependencies: - fill-range "^7.1.1" - -browserslist@^4.22.2: - version "4.22.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.2.tgz#704c4943072bd81ea18997f3bd2180e89c77874b" - integrity sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A== - dependencies: - caniuse-lite "^1.0.30001565" - electron-to-chromium "^1.4.601" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== - -call-bind@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== - dependencies: - function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - -caniuse-lite@^1.0.30001565: - version "1.0.30001579" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001579.tgz#45c065216110f46d6274311a4b3fcf6278e0852a" - integrity sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -ci-info@^3.2.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -cjs-module-lexer@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== - -collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -component-emitter@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" - integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -content-disposition@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" - integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== - dependencies: - safe-buffer "5.2.1" - -content-type@~1.0.4, content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - -convert-source-map@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" - integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== - -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== - -cookiejar@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" - integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== - -create-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-config "^29.7.0" - jest-util "^29.7.0" - prompts "^2.0.1" - -cross-spawn@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" - integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== - dependencies: - ms "2.1.2" - -dedent@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" - integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== - -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - -define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== - dependencies: - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - -dezalgo@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81" - integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig== - dependencies: - asap "^2.0.0" - wrappy "1" - -diff-sequences@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" - integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== - -dotenv@^16.0.3: - version "16.3.2" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.2.tgz#3cb611ce5a63002dbabf7c281bc331f69d28f03f" - integrity sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ== - -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - -electron-to-chromium@^1.4.601: - version "1.4.640" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.640.tgz#76290a36fa4b5f1f4cadaf1fc582478ebb3ac246" - integrity sha512-z/6oZ/Muqk4BaE7P69bXhUhpJbUM9ZJeka43ZwxsDshKtePns4mhBlh8bU5+yrnOnz3fhG82XLzGUXazOmsWnA== - -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" - merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== - -expect@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== - dependencies: - "@jest/expect-utils" "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - -express@^4.19.2: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.6.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -fast-json-stable-stringify@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-safe-stringify@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - -fill-range@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" - integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -follow-redirects@^1.0.0: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -formidable@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.2.tgz#fa973a2bec150e4ce7cac15589d7a25fc30ebd89" - integrity sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g== - dependencies: - dezalgo "^1.0.4" - hexoid "^1.0.0" - once "^1.4.0" - qs "^6.11.0" - -forwarded@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" - integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@^2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== - dependencies: - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== - -glob@^7.1.3, glob@^7.1.4: - version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" - integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.1.1" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - -graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - -hexoid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" - integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - -http-proxy-middleware@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" - integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== - dependencies: - "@types/http-proxy" "^1.17.8" - http-proxy "^1.18.1" - is-glob "^4.0.1" - is-plain-obj "^3.0.0" - micromatch "^4.0.2" - -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https/-/https-1.0.0.tgz#3c37c7ae1a8eeb966904a2ad1e975a194b7ed3a4" - integrity sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg== - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-glob@^4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" - integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== - -istanbul-lib-instrument@^5.0.4: - version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-instrument@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz#71e87707e8041428732518c6fb5211761753fbdf" - integrity sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - -istanbul-lib-report@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" - integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jest-changed-files@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== - dependencies: - execa "^5.0.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - -jest-circus@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.7.0" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - pretty-format "^29.7.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== - dependencies: - "@jest/core" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - chalk "^4.0.0" - create-jest "^29.7.0" - exit "^0.1.2" - import-local "^3.0.2" - jest-config "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - yargs "^17.3.1" - -jest-config@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.7.0" - "@jest/types" "^29.6.3" - babel-jest "^29.7.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.7.0" - jest-environment-node "^29.7.0" - jest-get-type "^29.6.3" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-runner "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.6.3" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - jest-get-type "^29.6.3" - jest-util "^29.7.0" - pretty-format "^29.7.0" - -jest-environment-node@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - -jest-haste-map@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== - dependencies: - "@jest/types" "^29.6.3" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - jest-worker "^29.7.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== - dependencies: - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-matcher-utils@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== - dependencies: - chalk "^4.0.0" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - -jest-pnp-resolver@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== - -jest-regex-util@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== - -jest-resolve-dependencies@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== - dependencies: - jest-regex-util "^29.6.3" - jest-snapshot "^29.7.0" - -jest-resolve@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.7.0" - jest-validate "^29.7.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - -jest-runner@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== - dependencies: - "@jest/console" "^29.7.0" - "@jest/environment" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.7.0" - jest-environment-node "^29.7.0" - jest-haste-map "^29.7.0" - jest-leak-detector "^29.7.0" - jest-message-util "^29.7.0" - jest-resolve "^29.7.0" - jest-runtime "^29.7.0" - jest-util "^29.7.0" - jest-watcher "^29.7.0" - jest-worker "^29.7.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/globals" "^29.7.0" - "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.7.0" - graceful-fs "^4.2.9" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - natural-compare "^1.4.0" - pretty-format "^29.7.0" - semver "^7.5.3" - -jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" - leven "^3.1.0" - pretty-format "^29.7.0" - -jest-watcher@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== - dependencies: - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.7.0" - string-length "^4.0.1" - -jest-worker@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== - dependencies: - "@jest/core" "^29.7.0" - "@jest/types" "^29.6.3" - import-local "^3.0.2" - jest-cli "^29.7.0" - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json5@^2.2.3: - version "2.2.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" - integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== - -jsonwebtoken@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" - integrity sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ== - dependencies: - jws "^3.2.2" - lodash.includes "^4.3.0" - lodash.isboolean "^3.0.3" - lodash.isinteger "^4.0.4" - lodash.isnumber "^3.0.3" - lodash.isplainobject "^4.0.6" - lodash.isstring "^4.0.1" - lodash.once "^4.0.0" - ms "^2.1.1" - semver "^7.5.4" - -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash.includes@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" - integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== - -lodash.isboolean@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" - integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== - -lodash.isinteger@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" - integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== - -lodash.isnumber@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" - integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== - -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== - -lodash.once@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" - integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== - dependencies: - semver "^7.5.3" - -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -methods@^1.1.2, methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== - -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.5" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" - integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== - dependencies: - braces "^3.0.2" - picomatch "^2.3.1" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mime@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimatch@^3.0.4, minimatch@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@2.1.3, ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== - -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== - dependencies: - path-key "^3.0.0" - -object-inspect@^1.9.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -path-key@^3.0.0, path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -pirates@^4.0.4: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== - -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -pretty-format@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" - integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== - dependencies: - "@jest/schemas" "^29.6.3" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - -proxy-addr@~2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" - integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== - dependencies: - forwarded "0.2.0" - ipaddr.js "1.9.1" - -pure-rand@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" - integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - -qs@^6.11.0: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-is@^18.0.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" - integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve.exports@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" - integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== - -resolve@^1.20.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - -safe-buffer@5.2.1, safe-buffer@^5.0.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.3.8, semver@^7.5.3, semver@^7.5.4: - version "7.5.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" - integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== - dependencies: - lru-cache "^6.0.0" - -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - -set-function-length@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.0.tgz#2f81dc6c16c7059bda5ab7c82c11f03a515ed8e1" - integrity sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w== - dependencies: - define-data-property "^1.1.1" - function-bind "^1.1.2" - get-intrinsic "^1.2.2" - gopd "^1.0.1" - has-property-descriptors "^1.0.1" - -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.3, signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - -statuses@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" - integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== - -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== - -strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -superagent@^8.1.2: - version "8.1.2" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.1.2.tgz#03cb7da3ec8b32472c9d20f6c2a57c7f3765f30b" - integrity sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA== - dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.4" - debug "^4.3.4" - fast-safe-stringify "^2.1.1" - form-data "^4.0.0" - formidable "^2.1.2" - methods "^1.1.2" - mime "2.6.0" - qs "^6.11.0" - semver "^7.3.8" - -supertest@^6.3.4: - version "6.3.4" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.4.tgz#2145c250570c2ea5d337db3552dbfb78a2286218" - integrity sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw== - dependencies: - methods "^1.1.2" - superagent "^8.1.2" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== - -type-detect@4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - -update-browserslist-db@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" - integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== - dependencies: - escalade "^3.1.1" - picocolors "^1.0.0" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - -v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== - dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== - dependencies: - makeerror "1.0.12" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.3.1: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/js/digital_signature.js b/js/digital_signature.js new file mode 100644 index 0000000..194e3bb --- /dev/null +++ b/js/digital_signature.js @@ -0,0 +1,7 @@ +var jwt = require('jsonwebtoken'); + +function generate_digital_signature(digital_key, body) { + return jwt.sign(body, digital_key, { algorithm: 'RS256' }); +} + +module.exports = generate_digital_signature; \ No newline at end of file diff --git a/js/digital_signature_test.js b/js/digital_signature_test.js new file mode 100644 index 0000000..19e8a2e --- /dev/null +++ b/js/digital_signature_test.js @@ -0,0 +1,33 @@ +const jwt = require('jsonwebtoken'); +require('dotenv').config(); +const { expect } = require('chai'); +const generate_digital_signature = require('./digital_signature'); + +const privateKey = process.env.PRIVATE.replace(/\\n/g, '\n'); +const publicKey = process.env.PUBLIC.replace(/\\n/g, '\n'); + +const body = { name: 'John Doe', email: 'john@example.com' }; + + +describe('generate_digital_signature', () => { + it('should generate a valid digital signature', () => { + const expectedSignature = jwt.sign(body, privateKey, { algorithm: 'RS256' }); + const actualSignature = generate_digital_signature(privateKey, body); + expect(actualSignature).to.equal(expectedSignature); + }); + + it('should throw an error if digital key is invalid', () => { + const invalidKey = 'invalid-digital-key'; + expect(() => generate_digital_signature(invalidKey, body)).to.throw(); + }); + + it('should be able to verify the key', () => { + const actualSignature = generate_digital_signature(privateKey, body); + + jwt.verify(actualSignature, publicKey, function(err, decoded) { + expect(decoded.email).to.equal(body.email); + expect(decoded.name).to.equal(body.name); + }); + }); + +}); diff --git a/js/package.json b/js/package.json new file mode 100644 index 0000000..96c55fe --- /dev/null +++ b/js/package.json @@ -0,0 +1,16 @@ +{ + "name": "digital-signature", + "version": "1.0.0", + "description": "JP Morgan Global Payments Digital Signature Sample", + "scripts": { + "test": "mocha digital_signature_test.js" + }, + "author": "jp morgan payments", + "license": "ISC", + "dependencies": { + "chai": "^4.3.7", + "dotenv": "^16.0.3", + "jsonwebtoken": "^9.0.0", + "mocha": "^10.2.0" + } +} \ No newline at end of file diff --git a/js/sample-authentication-code/config/config.json b/js/sample-authentication-code/config/config.json deleted file mode 100644 index 521888c..0000000 --- a/js/sample-authentication-code/config/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "client_id": "", - "certPath": "./config/.pem", - "jti": "12345", - "privateKey": "./config/.key", - "audience": "https://idag2.jpmorganchase.com/adfs/oauth2/token", - "expiresIn": "8h", - "algorithm": "RS256", - "client_assertion_type": "urn:ietf:params:oauth:client-assertion-type:jwt-bearer", - "grant_type": "client_credentials", - "resource_id": "", - "ida_url": "https://idag2.jpmorganchase.com/adfs/oauth2/token", - "content_type": "application/x-www-form-urlencoded" -} \ No newline at end of file diff --git a/js/sample-authentication-code/generateCertificates.js b/js/sample-authentication-code/generateCertificates.js deleted file mode 100644 index 67578ee..0000000 --- a/js/sample-authentication-code/generateCertificates.js +++ /dev/null @@ -1,171 +0,0 @@ -/* -* This utility script is used to create a certificate request (CSR) along with a self-signed X509 certificate (CRT) using -* node-forge which is a npm library containing various cryptography utilities to create and handle communicate protocols. -* -* generateCertificates.js is a script that will ask for various information that is incorporated into your certificate request -* which can then be used with an approved certificate authority (CA) to receive a signed certificate to on-board to PROD environment. -* The script will also generate a self-signed certificate using basic extensions that can be used to on-board to CAT environment. -* -* Note: node must be installed on your machine to download and install any external dependencies as well as run the individual -* javascript files. Please reference the documentation on https://nodejs.org/en/docs/ for any help on setup/installation. -* */ - -var prompt = require('prompt-sync')(); -var forge = require('node-forge'); -var fs = require('fs'); - -try { - console.log('\n***Note: For PROD environment, a certificate must be created by a J.P. Morgan approved Certificate Authority (CA). ' + - 'Utility will use the information provided to create a certificate request which can then be given to a CA ' + - 'and a self-signed certificate which could be leveraged to on-board to the CAT environment.***'); - - // user input for certificate request - console.log('\nYou are about to be asked to enter information that will be incorporated into your certificate request.'); - var countryName = requirePrompt('Country Name (2 letter code): '); - var stateName = requirePrompt('State or Province Name (2 letter code): '); - var cityName = requirePrompt('Locality Name (eg, city): '); - var organizationName = requirePrompt('Organization Name (eg, company): '); - var organizationUnitName = requirePrompt('Organizational Unit Name (eg, section): '); - var commonName = requirePrompt('Common Name (eg, identifier): '); - - // openssl genrsa -out key 2048 - console.log('\nGenerating 2048-bit key-pair...'); - var keys = forge.pki.rsa.generateKeyPair(2048); - console.log('Key-pair created successfully...'); - - // openssl req -new -config ../openssl.cnf -key key -out csr - // Note: Does not actually use .cnf, read in .key or output .csr; done in-memory - // Note: Could skip creating CSR here if you're the one generating the keys - console.log('Creating certification request...'); - var csr = forge.pki.createCertificationRequest(); - csr.publicKey = keys.publicKey; - csr.setSubject([ - { - name: 'countryName', - value: countryName.valueOf() - }, - { - shortName: 'ST', - value: stateName.valueOf() - }, - { - name: 'localityName', - value: cityName.valueOf() - }, - { - name: 'organizationName', - value: organizationName.valueOf() - }, - { - shortName: 'OU', - value: organizationUnitName.valueOf() - }, - { - name: 'commonName', - value: commonName.valueOf() - } - ]); - - // sign certification request - csr.sign(keys.privateKey); - console.log('Certification request created...'); - - // PEM-format keys and csr - var pem = { - privateKey: forge.pki.privateKeyToPem(keys.privateKey), - publicKey: forge.pki.publicKeyToPem(keys.publicKey), - csr: forge.pki.certificationRequestToPem(csr) - }; - - // Log PEM-formatted keys and csr, Uncomment code below if needed. - // console.log('\nKey-Pair:'); - // console.log(pem.privateKey); - // console.log(pem.publicKey); - // - // console.log('\nCertification Request:'); - // console.log(pem.csr); - - // write files to config directory - fs.writeFileSync(__dirname + '/config/privateKey.key', pem.privateKey); - fs.writeFileSync(__dirname + '/config/publicKey.key', pem.publicKey); - fs.writeFileSync(__dirname + '/config/certificateRequest.pem', pem.csr); - - /* - * Code below is to create sample self-signed certificate using CSR. - * */ - console.log('Creating self-signed certificate...'); - var cert = forge.pki.createCertificate(); - // set_serial 01 - cert.serialNumber = '01'; - // -days 365 - cert.validity.notBefore = new Date(); - cert.validity.notAfter = new Date(); - cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); - // subject from CSR - cert.setSubject(csr.subject.attributes); - // issuer from CSR - cert.setIssuer(csr.subject.attributes); - // set basic extensions - cert.setExtensions([ - { - name: 'basicConstraints', - cA: true - }, - { - name: 'keyUsage', - keyCertSign: true, - digitalSignature: true, - nonRepudiation: true, - keyEncipherment: true, - dataEncipherment: true - }, - { - name: 'extKeyUsage', - serverAuth: true, - clientAuth: true, - codeSigning: true, - emailProtection: true, - timeStamping: true - }, - { - name: 'nsCertType', - client: true, - server: true, - email: true, - objsign: true, - sslCA: true, - emailCA: true, - objCA: true - } - ]); - cert.publicKey = csr.publicKey; - - //self-sign certificate - cert.sign(keys.privateKey); - - // PEM-format self-signed crt - var crtPEM = forge.pki.certificateToPem(cert); - - // Log PEM-formatted self-signed crt, Uncomment code below if needed. - // console.log('\nSelf-Signed Certification:'); - // console.log(crtPEM); - - // write file to config directory - fs.writeFileSync(__dirname + '/config/selfSignedCertificate.pem', crtPEM); - console.log('Certificate created...'); - -} catch (error) { - console.log(error); -} - -function requirePrompt(promptString) { - var input = prompt(promptString); - if (input === null || input === '') { - console.log('Field was not given a value, please provide a value when prompted'); - input = prompt(promptString); - if (input === null || input === '') { - throw new Error('A field was not given a value'); - } - } - return input; -} \ No newline at end of file diff --git a/js/sample-authentication-code/getAccessToken.js b/js/sample-authentication-code/getAccessToken.js deleted file mode 100644 index 83eaea1..0000000 --- a/js/sample-authentication-code/getAccessToken.js +++ /dev/null @@ -1,85 +0,0 @@ -"use strict"; -const fs = require('fs'); -const jwt = require('jsonwebtoken'); -const axios = require('axios'); -const express = require('express'); -const bodyParser = require('body-parser'); -const qs = require('querystring'); -const upperCase = require('upper-case'); -const forge = require('node-forge'); -const config = require('./config/config.json'); - -const {pki, md} = forge; -const app = express(); - -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ - extended: true -})); - -var payload1 = { - jti: config.jti -}; - -// PublicKey -var certPath = config.certPath; - -// PrivateKey -var privateKEY = fs.readFileSync(config.privateKey, 'utf8'); - -// Issuer -var i = config.client_id; -// Subject -var s = config.client_id; -// Audience -var a = config.audience; - -// SIGNING OPTIONS... -var signOptions = { - issuer: i, - subject: s, - audience: a, - expiresIn: config.expiresIn, - algorithm: config.algorithm, - keyid: getCertThumbPrint(certPath) -}; - -var token = jwt.sign(payload1, privateKEY, signOptions); -let access_token = ''; - -var payload = { - client_id: config.client_id, - client_assertion_type: config.client_assertion_type, - client_assertion: token, - grant_type: config.grant_type, - resource: config.resource_id -}; - -const options = { - headers: { - 'Content-Type': config.content_type - }, - proxy: false -}; - -let url = config.ida_url; - -axios.post(url, qs.stringify(payload), options).then(resp => { - access_token = resp.data.access_token; - console.log(JSON.stringify(resp.data, null, 2)); -}).catch((err) => { - console.log("Error ===> ", err); -}); - -// get the ThumbPrint from Public Certificate using RSA -function getCertThumbPrint(pathName) { - var pem = fs.readFileSync(pathName); - var cert = forge.pki.certificateFromPem(pem); - var asn1 = forge.pki.certificateToAsn1(cert); - var der = forge.asn1.toDer(asn1); - var sha1 = forge.md.sha1.create(); - sha1.update(der.bytes()); - var sha256 = forge.md.sha256.create(); - sha256.update(der.bytes()); - return upperCase(sha1.digest().toHex()); -} \ No newline at end of file diff --git a/js/sample-authentication-code/getJWT.js b/js/sample-authentication-code/getJWT.js deleted file mode 100644 index cb8afad..0000000 --- a/js/sample-authentication-code/getJWT.js +++ /dev/null @@ -1,61 +0,0 @@ -"use strict"; -const fs = require('fs'); -const jwt = require('jsonwebtoken'); -const express = require('express'); -const bodyParser = require('body-parser'); -const upperCase = require('upper-case'); -const forge = require('node-forge'); -const config = require('./config/config.json'); - -const {pki, md} = forge; -const app = express(); - -app.use(bodyParser.json()); -app.use(bodyParser.urlencoded({ - extended: true -})); - -var payload1 = { - jti: config.jti -}; - -// PublicKey -var certPath = config.certPath; - -// PrivateKey -var privateKEY = fs.readFileSync(config.privateKey, 'utf8'); - -// Issuer -var i = config.client_id; -// Subject -var s = config.client_id; -// Audience -var a = config.audience; - -// SIGNING OPTIONS... -var signOptions = { - issuer: i, - subject: s, - audience: a, - expiresIn: config.expiresIn, - algorithm: config.algorithm, - keyid: getCertThumbPrint(certPath) -}; - -var token = jwt.sign(payload1, privateKEY, signOptions); -var value = token.toString().replace('\n', ''); -// Remove new lines for proper format -console.log("JWT: " + value); - -// Get the ThumbPrint from Public Certificate using RSA -function getCertThumbPrint(pathName) { - var pem = fs.readFileSync(pathName); - var cert = forge.pki.certificateFromPem(pem); - var asn1 = forge.pki.certificateToAsn1(cert); - var der = forge.asn1.toDer(asn1); - var sha1 = forge.md.sha1.create(); - sha1.update(der.bytes()); - var sha256 = forge.md.sha256.create(); - sha256.update(der.bytes()); - return upperCase(sha1.digest().toHex()); -} \ No newline at end of file diff --git a/js/sample-authentication-code/package.json b/js/sample-authentication-code/package.json deleted file mode 100644 index 1afc47e..0000000 --- a/js/sample-authentication-code/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "sample-auth-code", - "version": "1.0.0", - "description": "Collection of scripts which can be used to simplify client on-boarding.", - "main": "generateCertificates.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "axios": "^1.6.7", - "body-parser": "^1.20.2", - "express": "^4.19.2", - "fs": "0.0.2", - "jsonwebtoken": "^9.0.0", - "node-forge": "^1.3.0", - "prompt-sync": "^4.2.0", - "querystring": "^0.2.0", - "upper-case": "^1.1.3" - } -} diff --git a/js/sample-authentication-code/sendFirstRequest.js b/js/sample-authentication-code/sendFirstRequest.js deleted file mode 100644 index cf40b9c..0000000 --- a/js/sample-authentication-code/sendFirstRequest.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * This script gives you the code for sending a request to one of our APIs - */ - -const axios = require("axios"); - -const url = "https://api-mock.payments.jpmorgan.com/tsapi/v1/payments"; - -const sendFirstRequest = async (body, accessToken) => { - try { - const response = await axios.post(url, body, { - headers: { - "Content-Type": "application/json", - Accept: "application/json", - Authorization: `Bearer ${accessToken}`, - }, - }); - console.log(response.data); - } catch (error) { - console.error(error); - } -}; diff --git a/js/yarn.lock b/js/yarn.lock new file mode 100644 index 0000000..651df96 --- /dev/null +++ b/js/yarn.lock @@ -0,0 +1,646 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chai@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +debug@4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +dotenv@^16.0.3: + version "16.0.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" + integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== + +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsonwebtoken@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz#d0faf9ba1cc3a56255fe49c0961a67e520c1926d" + integrity sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw== + dependencies: + jws "^3.2.2" + lodash "^4.17.21" + ms "^2.1.1" + semver "^7.3.8" + +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loupe@^2.3.1: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +mocha@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" + integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== + dependencies: + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +safe-buffer@^5.0.1, safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +semver@^7.3.8: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/metrics/README.md b/metrics/README.md new file mode 100644 index 0000000..66002fc --- /dev/null +++ b/metrics/README.md @@ -0,0 +1,10 @@ +# Metrics Gathering + +We've created a bash script that runs daily to collect our metrics and store them as csv. +This is because _currently_ GitHub is only storing the last 14days worth of data. + +We use the [github_traffic_stats](https://github.com/nchah/github-traffic-stats) python package to gather our metrics in three csv files. + +Then we have created merge.sh to merge these metrics with the previous days csv and then sort by date order. + +We are storing our latest metrics files on a branch called 'metrics'. This is because we don't want to push directly to main. diff --git a/metrics/merge.sh b/metrics/merge.sh new file mode 100755 index 0000000..1d9ca24 --- /dev/null +++ b/metrics/merge.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# Check if an argument is provided +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi +# Access the first command-line argument +file_name="$1" + +# Check if an argument is provided +if [ -z "$2" ]; then + echo "Usage: $0 " + exit 1 +fi +# Access the first command-line argument +output_file="./${2}.csv" + +# Specify the input file names +file1="1.csv" +file2=$(find "./" -type f -name "*-$file_name" -print -quit) + +# Specify the output file name + +cp "$output_file" "$file1" + +# Check if the output file already exists and remove it +if [ -e "$output_file" ]; then + rm "$output_file" +fi + + + +# Copy the header from the first file to the output file +head -n 1 "$file1" > "$output_file" +# Use awk to merge the files, taking the row from the newer file in case of duplicates +awk -F, 'NR==FNR && FNR>1 {a[$2]=$0; next} FNR>1 {a[$2]=$0} END {for (i in a) print a[i]}' "$file1" "$file2" >> "$output_file" + +echo "Files merged successfully. Output file: $output_file" +echo "Sorting Output file..." + +# Check if the file exists +if [ ! -f "$output_file" ]; then + echo "Error: File '$output_file' not found." + exit 1 +fi + +# Sort the CSV file by the second column (date) +sorted_csv_file="./${2}-sorted.csv" +if [ -e "$sorted_csv_file" ]; then + rm "$sorted_csv_file" +fi +{ head -n 1 "$output_file"; tail -n +2 "$output_file" | sort -t ',' -k2,2; } > "$sorted_csv_file" + +echo "CSV file sorted by date. Output file: $sorted_csv_file" + + +if [ -e "$file1" ]; then + rm "$file1" +fi +if [ -e "$file2" ]; then + rm "$file2" +fi \ No newline at end of file diff --git a/postman/Authentication.postman_collection.json b/postman/Authentication.postman_collection.json deleted file mode 100644 index a58c707..0000000 --- a/postman/Authentication.postman_collection.json +++ /dev/null @@ -1,597 +0,0 @@ -{ - "info": { - "_postman_id": "55b2f95c-bee7-4f22-9252-aac9c137fd67", - "name": "Authentication", - "description": "This is a collection with examples on connecting to J.P. Morgan APIs using either OAuth or mTLS.\n\nYou will find instructions on how to use both within the collection.", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "26402882" - }, - "item": [ - { - "name": "TLS/SSL", - "item": [ - { - "name": "JWT/Digital Signature", - "item": [ - { - "name": "Initiate a Payment", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 202\", function () {", - " pm.response.to.have.code(202);", - " var jsonData = pm.response.json();", - " pm.environment.set(\"endToEndId\", jsonData.paymentInitiationResponse.endToEndId);", - "});", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "text/xml", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{{JWSPayload}}", - "options": { - "raw": { - "language": "xml" - } - } - }, - "url": { - "raw": "https://apigatewaycat.jpmorgan.com/tsapi/v1/payments", - "protocol": "https", - "host": [ - "apigatewaycat", - "jpmorgan", - "com" - ], - "path": [ - "tsapi", - "v1", - "payments" - ] - } - }, - "response": [] - }, - { - "name": "Sign Payload", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "const navigator = {} //fake a navigator object for the lib\r", - "const window = {} //fake a window object for the lib\r", - "pm.sendRequest(\"https://kjur.github.io/jsrsasign/jsrsasign-latest-all-min.js\", (error, response) => {\r", - "if (error || response.code !== 200) {\r", - " pm.expect.fail('Could not load external library')\r", - "}\r", - "eval(response.text())\r", - "\r", - "var myRequest = JSON.stringify(request.data)\r", - "myRequest = myRequest.replace(/\\\\n/g,\"\")\r", - "myRequest = myRequest.replace(/\\\\r/g,\"\")\r", - "myRequest = myRequest.replace(/\\\\/g,\"\")\r", - "mylength = myRequest.length\r", - "myRequest = myRequest.substring(1,mylength-1)\r", - "// console.log(mylength)\r", - "console.log(myRequest)\r", - "\r", - "var header = {\"alg\" : \"RS256\"}\r", - "\r", - "var sHeader = JSON.stringify(header)\r", - "var sPayload = JSON.stringify(data)\r", - "\r", - "var sJWT = KJUR.jws.JWS.sign(header.alg, sHeader, myRequest,pm.environment.get(\"Priv_Key\"))\r", - "console.log(sJWT)\r", - "console.log(pm.environment.get(\"Priv_Key\"))\r", - "pm.environment.set(\"JWSPayload\",sJWT)\r", - "//console.log(sJWT)\r", - "})" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "myDateVar = new Date()\r", - "\r", - "myFDate = myDateVar.getFullYear() + \"-\" +\r", - " (\"0\" + (myDateVar.getMonth() + 1)).slice(-2) + \"-\" +\r", - " (\"0\" + (myDateVar.getDate() + 1)).slice(-2)\r", - "\r", - "//Create the endToEndId\r", - "myE2E = \"ACHC\" + \r", - " (\"0\" + (myDateVar.getMonth() + 1)).slice(-2) + \r", - " (\"0\" + myDateVar.getDate()).slice(-2) +\r", - " (\"0\" + myDateVar.getHours()).slice(-2) + \r", - " (\"0\" + myDateVar.getMinutes()).slice(-2) + \r", - " (\"0\" + myDateVar.getMilliseconds()).slice(-3) \r", - "\r", - "pm.environment.set(\"End2EndID\",JSON.stringify(myE2E))\r", - "pm.environment.set(\"execDate\",JSON.stringify(myFDate))" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"payments\": {\r\n \"requestedExecutionDate\": \"2023-09-04\",\r\n \"paymentAmount\": 25,\r\n \"paymentType\": \"RTP\",\r\n \"paymentIdentifiers\": {\r\n \"endToEndId\": \"uf169382486039811\"\r\n },\r\n \"paymentCurrency\": \"EUR\",\r\n \"transferType\": \"CREDIT\",\r\n \"debtor\": {\r\n \"debtorName\": \"OBGLRTPCL1 Account\",\r\n \"debtorAccount\": {\r\n \"accountId\": \"DE88501108006231400596\",\r\n \"accountCurrency\": \"EUR\",\r\n \"accountType\": \"IBAN\"\r\n }\r\n },\r\n \"debtorAgent\": {\r\n \"financialInstitutionId\": {\r\n \"bic\": \"CHASDEFX\"\r\n }\r\n },\r\n \"creditor\": {\r\n \"creditorName\": \"UNICORNUAT Account\",\r\n \"creditorAccount\": {\r\n \"accountId\": \"DE45501108000041287103\",\r\n \"accountCurrency\": \"EUR\"\r\n }\r\n },\r\n \"creditorAgent\": {\r\n \"financialInstitutionId\": {\r\n \"bic\": \"CHASDEFX\"\r\n }\r\n }\r\n }\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://postman-echo.com/get", - "protocol": "https", - "host": [ - "postman-echo", - "com" - ], - "path": [ - "get" - ] - } - }, - "response": [] - } - ], - "description": "This collection demonstrates the process of generating a JWT/Digital Signature directly from Postman. Certain requests within our UAT/Prod environments necessitate this encoding in the JSON body.\n\nTo execute this collection:\n\n1. Acquire your certificates and onboard them to J.P. Morgan following instructions here: [http://developer.jpmorgan.com](http://developer.jpmorgan.com/).\n2. Upload these certificates to postman following directions: [https://learning.postman.com/docs/sending-requests/certificates/#adding-client-certificates](https://learning.postman.com/docs/sending-requests/certificates/#adding-client-certificates).\n \n3. Collect your private key and include it in your Postman variables as 'priv_key'.\n4. Copy the request body into the sign payload request.\n5. Execute the sign payload request.\n6. Execute the initiate a payment request." - }, - { - "name": "Global-payments-payment-status", - "request": { - "method": "GET", - "header": [], - "url": { - "raw": "https://apigatewaycat.jpmorgan.com/tsapi/v1/payments/status?endToEndId=uf1682944782231", - "protocol": "https", - "host": [ - "apigatewaycat", - "jpmorgan", - "com" - ], - "path": [ - "tsapi", - "v1", - "payments", - "status" - ], - "query": [ - { - "key": "endToEndId", - "value": "uf1682944782231" - } - ] - } - }, - "response": [] - } - ], - "description": "This collection illustrates how to access our APIs utilizing mTLS authentication.\n\nDetailed guidance on generating your certificates and integrating them with J.P. Morgan can be found at [http://developer.jpmorgan.com](http://developer.jpmorgan.com/).\n\nSubsequently, you can incorporate them into Postman by following these instructions: [https://learning.postman.com/docs/sending-requests/certificates/#adding-client-certificates](https://learning.postman.com/docs/sending-requests/certificates/#adding-client-certificates)." - }, - { - "name": "OAuth", - "item": [ - { - "name": "JWT/Digital Signature", - "item": [ - { - "name": "Initiate a Payment", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Status code is 202\", function () {", - " pm.response.to.have.code(202);", - " var jsonData = pm.response.json();", - " pm.environment.set(\"endToEndId\", jsonData.paymentInitiationResponse.endToEndId);", - "});", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [ - { - "key": "Content-Type", - "value": "text/xml", - "type": "text" - } - ], - "body": { - "mode": "raw", - "raw": "{{JWSPayload}}", - "options": { - "raw": { - "language": "xml" - } - } - }, - "url": { - "raw": "https://apigatewaycat.jpmorgan.com/tsapi/v1/payments", - "protocol": "https", - "host": [ - "apigatewaycat", - "jpmorgan", - "com" - ], - "path": [ - "tsapi", - "v1", - "payments" - ] - } - }, - "response": [] - }, - { - "name": "Sign Payload", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "const navigator = {} //fake a navigator object for the lib\r", - "const window = {} //fake a window object for the lib\r", - "pm.sendRequest(\"https://kjur.github.io/jsrsasign/jsrsasign-latest-all-min.js\", (error, response) => {\r", - "if (error || response.code !== 200) {\r", - " pm.expect.fail('Could not load external library')\r", - "}\r", - "eval(response.text())\r", - "\r", - "var myRequest = JSON.stringify(request.data)\r", - "myRequest = myRequest.replace(/\\\\n/g,\"\")\r", - "myRequest = myRequest.replace(/\\\\r/g,\"\")\r", - "myRequest = myRequest.replace(/\\\\/g,\"\")\r", - "mylength = myRequest.length\r", - "myRequest = myRequest.substring(1,mylength-1)\r", - "// console.log(mylength)\r", - "console.log(myRequest)\r", - "\r", - "var header = {\"alg\" : \"RS256\"}\r", - "\r", - "var sHeader = JSON.stringify(header)\r", - "var sPayload = JSON.stringify(data)\r", - "\r", - "var sJWT = KJUR.jws.JWS.sign(header.alg, sHeader, myRequest,pm.environment.get(\"Priv_Key\"))\r", - "console.log(sJWT)\r", - "console.log(pm.environment.get(\"Priv_Key\"))\r", - "pm.environment.set(\"JWSPayload\",sJWT)\r", - "//console.log(sJWT)\r", - "})" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "myDateVar = new Date()\r", - "\r", - "myFDate = myDateVar.getFullYear() + \"-\" +\r", - " (\"0\" + (myDateVar.getMonth() + 1)).slice(-2) + \"-\" +\r", - " (\"0\" + (myDateVar.getDate() + 1)).slice(-2)\r", - "\r", - "//Create the endToEndId\r", - "myE2E = \"ACHC\" + \r", - " (\"0\" + (myDateVar.getMonth() + 1)).slice(-2) + \r", - " (\"0\" + myDateVar.getDate()).slice(-2) +\r", - " (\"0\" + myDateVar.getHours()).slice(-2) + \r", - " (\"0\" + myDateVar.getMinutes()).slice(-2) + \r", - " (\"0\" + myDateVar.getMilliseconds()).slice(-3) \r", - "\r", - "pm.environment.set(\"End2EndID\",JSON.stringify(myE2E))\r", - "pm.environment.set(\"execDate\",JSON.stringify(myFDate))" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "{\r\n \"payments\": {\r\n \"requestedExecutionDate\": \"2023-09-04\",\r\n \"paymentAmount\": 25,\r\n \"paymentType\": \"RTP\",\r\n \"paymentIdentifiers\": {\r\n \"endToEndId\": \"uf169382486039811\"\r\n },\r\n \"paymentCurrency\": \"EUR\",\r\n \"transferType\": \"CREDIT\",\r\n \"debtor\": {\r\n \"debtorName\": \"OBGLRTPCL1 Account\",\r\n \"debtorAccount\": {\r\n \"accountId\": \"DE88501108006231400596\",\r\n \"accountCurrency\": \"EUR\",\r\n \"accountType\": \"IBAN\"\r\n }\r\n },\r\n \"debtorAgent\": {\r\n \"financialInstitutionId\": {\r\n \"bic\": \"CHASDEFX\"\r\n }\r\n },\r\n \"creditor\": {\r\n \"creditorName\": \"UNICORNUAT Account\",\r\n \"creditorAccount\": {\r\n \"accountId\": \"DE45501108000041287103\",\r\n \"accountCurrency\": \"EUR\"\r\n }\r\n },\r\n \"creditorAgent\": {\r\n \"financialInstitutionId\": {\r\n \"bic\": \"CHASDEFX\"\r\n }\r\n }\r\n }\r\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://postman-echo.com/get", - "protocol": "https", - "host": [ - "postman-echo", - "com" - ], - "path": [ - "get" - ] - } - }, - "response": [] - } - ], - "description": "This collection demonstrates the process of generating a JWT/Digital Signature directly from Postman. Certain requests within our UAT/Prod environments necessitate this encoding in the JSON body. However, you still have the option to provide your access token for OAuth authentication.\n\nTo execute this collection:\n\n1. Acquire your CLIENT_ID and CLIENT_SECRET. Detailed instructions can be found here: [https://developer.payments.jpmorgan.com/quick-start](https://developer.payments.jpmorgan.com/quick-start)\n \n2. Insert these values into the authorization request for OAuth getAccessToken.\n \n3. Execute the getAccessToken request.\n \n4. Collect your private key and include it in your Postman variables as 'priv_key'.\n \n5. Copy the request body into the sign payload request.\n \n6. Execute the sign payload request.\n \n7. Execute the initiate a payment request." - }, - { - "name": "getAccessToken", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"Save access token\", function () {", - " var jsonData = pm.response.json();", - " var accessToken = jsonData.access_token", - " pm.collectionVariables.set(\"access_token\", accessToken);", - "});" - ], - "type": "text/javascript" - } - } - ], - "request": { - "auth": { - "type": "basic", - "basic": [ - { - "key": "password", - "value": "CLIENT_SECRET", - "type": "string" - }, - { - "key": "username", - "value": "CLIENT_ID", - "type": "string" - } - ] - }, - "method": "POST", - "header": [], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "grant_type", - "value": "client_credentials", - "type": "text" - }, - { - "key": "scope", - "value": "jpm:payments:sandbox", - "type": "text" - } - ] - }, - "url": { - "raw": "https://id.payments.jpmorgan.com/am/oauth2/alpha/access_token", - "protocol": "https", - "host": [ - "id", - "payments", - "jpmorgan", - "com" - ], - "path": [ - "am", - "oauth2", - "alpha", - "access_token" - ] - } - }, - "response": [] - }, - { - "name": "Online-payments-create-a-payment", - "request": { - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - }, - { - "key": "Content-Type", - "value": "application/json" - }, - { - "key": "merchant-id", - "value": "998482157630" - }, - { - "key": "minorVersion", - "value": "" - }, - { - "key": "request-id", - "value": "10cc0270-7bed-11e9-a188-1763956dd7f6" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"captureMethod\": \"NOW\",\n \"amount\": 1234,\n \"currency\": \"USD\",\n \"merchant\": {\n \"merchantSoftware\": {\n \"companyName\": \"Payment Company\",\n \"productName\": \"Application Name\",\n \"version\": \"1.235\"\n },\n \"merchantCategoryCode\": \"4899\"\n },\n \"paymentMethodType\": {\n \"card\": {\n \"accountNumber\": \"4012000033330026\",\n \"expiry\": {\n \"month\": 5,\n \"year\": 2027\n },\n \"isBillPayment\": true\n }\n },\n \"initiatorType\": \"CARDHOLDER\",\n \"accountOnFile\": \"NOT_STORED\",\n \"isAmountFinal\": true\n}" - }, - "url": { - "raw": "https://api-mock.payments.jpmorgan.com/api/v2/payments", - "protocol": "https", - "host": [ - "api-mock", - "payments", - "jpmorgan", - "com" - ], - "path": [ - "api", - "v2", - "payments" - ] - } - }, - "response": [] - }, - { - "name": "Global-payments-init-a-payment", - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{access_token}}", - "type": "string" - } - ] - }, - "method": "POST", - "header": [ - { - "key": "Accept", - "value": "application/json" - }, - { - "key": "Content-Type", - "value": "application/json" - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"payments\": {\n \"possibleDuplicateMessage\": false,\n \"paymentIdentifiers\": {\n \"endToEndId\": \"AD202109311354152\"\n },\n \"requestedExecutionDate\": \"2023-04-22\",\n \"transferType\": \"CREDIT\",\n \"paymentCurrency\": \"GBP\",\n \"paymentAmount\": 650,\n \"paymentType\": \"RTP\",\n \"debtor\": {\n \"debtorAccount\": {\n \"accountId\": \"12311871\",\n \"accountCurrency\": \"GBP\",\n \"accountType\": \"DDA\"\n },\n \"ultimateDebtor\": {\n \"ultimateDebtorName\": \"Wayne Thompson\",\n \"postalAddress\": {\n \"addressType\": \"ADDR\",\n \"streetName\": \"Lennon Road\",\n \"buildingNumber\": \"22\",\n \"townName\": \"Liverpool\",\n \"country\": \"GB\"\n },\n \"countryOfResidence\": \"GB\",\n \"organizationId\": {\n \"bic\": \"CHASGB2L\",\n \"id\": \"40025916\"\n }\n }\n },\n \"debtorAgent\": {\n \"financialInstitutionId\": {\n \"bic\": \"CHASGB2L\"\n }\n },\n \"creditorAgent\": {\n \"financialInstitutionId\": {\n \"clearingSystemId\": {\n \"id\": \"185008\"\n }\n }\n },\n \"creditor\": {\n \"creditorName\": \"David Burn\",\n \"postalAddress\": {\n \"addressType\": \"ADDR\",\n \"streetName\": \"Fratton Park\",\n \"buildingNumber\": \"411\",\n \"postalCode\": \"PO48RA\",\n \"townName\": \"Portsmouth\",\n \"country\": \"GB\",\n \"countrySubDvsn\": \"Hampshire\"\n },\n \"countryOfResidence\": \"GB\",\n \"creditorAccount\": {\n \"accountId\": \"87654321\"\n },\n \"ultimateCreditor\": {\n \"ultimateCreditorName\": \"Clint Hall\",\n \"individualId\": {\n \"id\": \"87654321\"\n },\n \"postalAddress\": {\n \"addressType\": \"ADDR\",\n \"streetName\": \"Fratton Park\",\n \"buildingNumber\": \"411\",\n \"postalCode\": \"PO48RA\",\n \"townName\": \"Portsmouth\",\n \"country\": \"GB\",\n \"countrySubDvsn\": \"Hampshire\"\n }\n }\n },\n \"purpose\": {\n \"code\": \"GDDS\",\n \"type\": \"CODE\"\n },\n \"remittanceInformation\": {\n \"unstructuredInformation\": [\n \"Payment for Macbook batteries Receipt #AXF23-LGG\"\n ]\n }\n }\n}" - }, - "url": { - "raw": "https://api-mock.payments.jpmorgan.com/tsapi/v1/payments", - "protocol": "https", - "host": [ - "api-mock", - "payments", - "jpmorgan", - "com" - ], - "path": [ - "tsapi", - "v1", - "payments" - ] - } - }, - "response": [] - } - ], - "description": "In this collection, we demonstrate the process of obtaining an access token to access our APIs. Additionally, we've provided sample requests for utilizing our APIs. Upon executing the 'getAccessToken' request, the token will be stored in a collection variable for use in subsequent requests.\n\nFor information on obtaining the CLIENT_ID and CLIENT_SECRET necessary for generating the access token, please refer to the following link: [https://developer.payments.jpmorgan.com/quick-start](https://developer.payments.jpmorgan.com/quick-start)" - }, - { - "name": "Backend-examples", - "item": [ - { - "name": "Basic Post Request", - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n \"payments\": {\n \"possibleDuplicateMessage\": false,\n \"paymentIdentifiers\": {\n \"endToEndId\": \"AD202109311354152\"\n },\n \"requestedExecutionDate\": \"2023-04-22\",\n \"transferType\": \"CREDIT\",\n \"paymentCurrency\": \"GBP\",\n \"paymentAmount\": 650,\n \"paymentType\": \"RTP\",\n \"debtor\": {\n \"debtorAccount\": {\n \"accountId\": \"12311871\",\n \"accountCurrency\": \"GBP\",\n \"accountType\": \"DDA\"\n },\n \"ultimateDebtor\": {\n \"ultimateDebtorName\": \"Wayne Thompson\",\n \"postalAddress\": {\n \"addressType\": \"ADDR\",\n \"streetName\": \"Lennon Road\",\n \"buildingNumber\": \"22\",\n \"townName\": \"Liverpool\",\n \"country\": \"GB\"\n },\n \"countryOfResidence\": \"GB\",\n \"organizationId\": {\n \"bic\": \"CHASGB2L\",\n \"id\": \"40025916\"\n }\n }\n },\n \"debtorAgent\": {\n \"financialInstitutionId\": {\n \"bic\": \"CHASGB2L\"\n }\n },\n \"creditorAgent\": {\n \"financialInstitutionId\": {\n \"clearingSystemId\": {\n \"id\": \"185008\"\n }\n }\n },\n \"creditor\": {\n \"creditorName\": \"David Burn\",\n \"postalAddress\": {\n \"addressType\": \"ADDR\",\n \"streetName\": \"Fratton Park\",\n \"buildingNumber\": \"411\",\n \"postalCode\": \"PO48RA\",\n \"townName\": \"Portsmouth\",\n \"country\": \"GB\",\n \"countrySubDvsn\": \"Hampshire\"\n },\n \"countryOfResidence\": \"GB\",\n \"creditorAccount\": {\n \"accountId\": \"87654321\"\n },\n \"ultimateCreditor\": {\n \"ultimateCreditorName\": \"Clint Hall\",\n \"individualId\": {\n \"id\": \"87654321\"\n },\n \"postalAddress\": {\n \"addressType\": \"ADDR\",\n \"streetName\": \"Fratton Park\",\n \"buildingNumber\": \"411\",\n \"postalCode\": \"PO48RA\",\n \"townName\": \"Portsmouth\",\n \"country\": \"GB\",\n \"countrySubDvsn\": \"Hampshire\"\n }\n }\n },\n \"purpose\": {\n \"code\": \"GDDS\",\n \"type\": \"CODE\"\n },\n \"remittanceInformation\": {\n \"unstructuredInformation\": [\n \"Payment for Macbook batteries Receipt #AXF23-LGG\"\n ]\n }\n }\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "http://localhost:8001/tsapi/v1/payments", - "protocol": "http", - "host": [ - "localhost" - ], - "port": "8001", - "path": [ - "tsapi", - "v1", - "payments" - ] - } - }, - "response": [] - }, - { - "name": "Basic Get Request", - "request": { - "method": "GET", - "header": [] - }, - "response": [] - } - ], - "description": "This folder includes basic requests for testing out our backend examples code." - } - ], - "variable": [ - { - "key": "CLIENT_SECRET", - "value": "y_OAgjpmVcEL1vpPDI9SXjIkdUYWBXpl8UIWHIVIlRW45zsl2q0EjfL_ffGkUDn02X2_RDZWe1buriJPrTwmeA" - }, - { - "key": "CLIENT_SECRET", - "value": "" - }, - { - "key": "access_token", - "value": "" - } - ] -} \ No newline at end of file diff --git a/postman/README.md b/postman/README.md deleted file mode 100644 index ce66990..0000000 --- a/postman/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Postman Collection: J.P. Morgan APIs - -This comprehensive collection provides examples of mTLS and OAuth requests tailored for J.P. Morgan APIs. - -Follow these steps to seamlessly import this file into your Postman environment: [Importing Data into Postman](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/) - -## Using the OAuth Collection - -1. Import the collection into Postman. -2. Refer to this guide to obtain your CLIENT_ID and CLIENT_SECRET: [J.P. Morgan Quick Start](https://developer.payments.jpmorgan.com/quick-start) -3. Insert the acquired values into the authorization section of the 'getAccessToken' request within the OAuth folder. -4. Execute the 'getAccessToken' request. -5. Proceed to execute other requests as needed. - -## Leveraging the mTLS Collection - -1. Import the collection into Postman. -2. Follow the directions provided to generate and onboard certificates from: [J.P. Morgan Developer Portal](https://developer.jpmorgan.com) -3. Upload the certificates to Postman by referring to: [Adding Client Certificates in Postman](https://learning.postman.com/docs/sending-requests/certificates/#adding-client-certificates) -4. Execute the requests as required to interact with the APIs securely. - -## Generating a JWT/Digital Signature - -1. Choose the appropriate Authentication method and navigate to the respective nested folder. -2. Integrate your private key into the Postman variables. -3. Copy the request body and paste it into the 'sign payload' request. -4. Execute the 'sign payload' request. -5. Proceed to execute the 'initiate a payment' request to complete the process. diff --git a/python/README.md b/python/README.md index 004cfbe..5ed07f6 100644 --- a/python/README.md +++ b/python/README.md @@ -1,10 +1,30 @@ -# J.P. Morgan Authentication examples - Python +# Digital Signature Python -Within this repository you can find example code for accessing our Payments APIs in Python. +A python implementation of generating a digital signature -Each folder contains: +## Requirements -- sample-authentication-code: This contains code scripts for generating digital signatures (also known as JWTs), gathering access tokens and generating certificates. -- backend-example: This is a fully functioning server that can handle sending requests to our APIs. +- Python3 install +- [Configured .env file](../README.md) -**Note this is not production code and is supplied to get developers started ** +## How to run + +You can run this code by running the tests or by including it in your codebase. + +1. Confirm `.env` configuration + +Ensure the certificate keys are configured in `.env` in this directory. You can find information on generating certificates at in our [readme](../README.md).It should include the following keys: + +```yaml +PRIVATE=... +PUBLIC= +``` + +2. Paste your json body into the body variable + +3. Install dependencies and start the test + +``` +pip install -r requirements.txt +python digital_signature_test.py +``` diff --git a/python/backend-example/README.md b/python/backend-example/README.md deleted file mode 100644 index cc57bcc..0000000 --- a/python/backend-example/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Python Backend Samples - -In this folder there are two code samples for connecting to our APIs using python. -Each sample is categorised by the authentication method you will use. - -** Note this is not production code and is supplied to get developers started ** - -## Requirements - -- Python 3 -- Configured .env file - -## How to run - OAuth - -1. Configure a '.env' file in the repository by adding your CLIENT_ID and CLIENT_SECRET, directions can be followed here: [https://developer.payments.jpmorgan.com/quick-start#add-an-api-to-your-project](https://developer.payments.jpmorgan.com/quick-start#add-an-api-to-your-project) (** this file should not be committed**) - -2. Install dependencies and start the server - -``` -yarn install -yarn start -``` - -3. Import the postman collection at the top of this repo to test out the server connection, you can use folder 'backend-examples'. Instructions for importing postman collections can be found ([here](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)) - -## How to run - SSL - -1. Configure a '.env' file in the repository by adding your SSL Certificate and Key to the file (** this file should not be committed**). You can copy the layout in .env.example. To upload your certificates you will need to onboard to [https://developer.jpmorgan.com](https://developer.jpmorgan.com) -2. Install dependencies and start the server - -``` -yarn install -yarn start -``` - -3. Import the postman collection at the top of this repo to test out the server connection, you can use folder 'backend-examples'. Instructions for importing postman collections can be found ([here](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)) diff --git a/python/backend-example/oauth/main.py b/python/backend-example/oauth/main.py deleted file mode 100644 index 9b65a37..0000000 --- a/python/backend-example/oauth/main.py +++ /dev/null @@ -1,93 +0,0 @@ -''' -This code shows a basic backend example for sending requests to our servers using OAuth -For POST requests we have included gathering a JWT, this may not be required. -You will provide your CLIENT_ID, CLIENT_SECRET and ACCESS_TOKEN_URL. -You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start - -Note this is not production code and is supplied to get developers started -''' -import requests -import signal -import sys -import sys -import json -from dotenv import load_dotenv - -import os -sys.path.append('../../sample-authentication-code') -from getAccessToken import get_access_token -from getJWT import generate_digital_signature -load_dotenv() -from http.server import BaseHTTPRequestHandler, HTTPServer - -url = "https://api-mock.payments.jpmorgan.com" -access_token_url=os.getenv('ACCESS_TOKEN_URL') -client_id=os.getenv('CLIENT_ID') -client_secret=os.getenv('CLIENT_SECRET') -digital_key = os.getenv('DIGITAL_KEY') - -class ApiProxy: - def start_server(self): - class ProxyHTTPRequestHandler(BaseHTTPRequestHandler): - protocol_version = "HTTP/1.0" - - def do_GET(self): - print("Received GET request") # Debugging statement - self._handle_request("get",requests.get) - - def do_DELETE(self): - print("Received DELETE request") # Debugging statement - self._handle_request("delete", requests.delete) - - def do_POST(self): - print("Received POST request") # Debugging statement - self._handle_request("post", requests.post) - - def do_PUT(self): - print("Received PUT request") # Debugging statement - self._handle_request("put", requests.put) - - def do_PATCH(self): - print("Received PATCH request") # Debugging statement - self._handle_request("patch", requests.patch) - - def _handle_request(self, method,requests_func): - final_url = url + self.path - print("Final URL:", final_url) - headers = dict(self.headers) - # Gathering the access token - access_token = get_access_token(url=access_token_url, client_id=client_id, client_secret=client_secret); - headers["Authorization"] = "Bearer " + access_token - - if method == "post": - data = self.rfile.read(int(self.headers["content-length"])).decode('UTF-8') - # This can be removed if not requiring a digital signature - encoded_data = generate_digital_signature(digital_key, json.loads(data)) - resp = requests_func(final_url, data=encoded_data, headers=headers) - - else: - resp = requests_func(final_url, headers=headers) - self.send_response(resp.status_code) - for key in resp.headers: - self.send_header(key, resp.headers[key]) - self.end_headers() - try: - self.wfile.write(resp.content) - self.wfile.flush() - except Exception as e: - print("Exception while writing response body:", e) - - - server_address = ('', 8001) - self.httpd = HTTPServer(server_address, ProxyHTTPRequestHandler) - print('proxy server is running') - self.httpd.serve_forever() - - -def exit_now(signum, frame): - sys.exit(0) - -if __name__ == '__main__': - proxy = ApiProxy() - signal.signal(signal.SIGTERM, exit_now) - proxy.start_server() \ No newline at end of file diff --git a/python/backend-example/ssl/main.py b/python/backend-example/ssl/main.py deleted file mode 100644 index efc5bf2..0000000 --- a/python/backend-example/ssl/main.py +++ /dev/null @@ -1,89 +0,0 @@ -''' -This code shows a basic backend example for sending requests to our servers using SSL -For POST requests we have included gathering a JWT, this may not be required. -You will provide your PRIVATE, PUBLIC and DIGITAL cert. -You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start - -Note this is not production code and is supplied to get developers started -''' -import requests -import signal -import sys -import sys -import json -from dotenv import load_dotenv - -import os -sys.path.append('../../sample-authentication-code') -from getJWT import generate_digital_signature -load_dotenv() -from http.server import BaseHTTPRequestHandler, HTTPServer - -url = "https://api-mock.payments.jpmorgan.com" - -digital_key=os.getenv('DIGITAL_KEY') -public_cert=os.getenv("PUBLIC") -private_cert=os.getenv("PRIVATE") - -class ApiProxy: - def start_server(self): - class ProxyHTTPRequestHandler(BaseHTTPRequestHandler): - protocol_version = "HTTP/1.0" - - def do_GET(self): - print("Received GET request") # Debugging statement - self._handle_request("get",requests.get) - - def do_DELETE(self): - print("Received DELETE request") # Debugging statement - self._handle_request("delete", requests.delete) - - def do_POST(self): - print("Received POST request") # Debugging statement - self._handle_request("post", requests.post) - - def do_PUT(self): - print("Received PUT request") # Debugging statement - self._handle_request("put", requests.put) - - def do_PATCH(self): - print("Received PATCH request") # Debugging statement - self._handle_request("patch", requests.patch) - - def _handle_request(self, method,requests_func): - final_url = url + self.path - print("Final URL:", final_url) - headers = dict(self.headers) - - if method == "post": - data = self.rfile.read(int(self.headers["content-length"])).decode('UTF-8') - # This can be removed if not requiring a digital signature - encoded_data = generate_digital_signature(digital_key, json.loads(data)) - resp = requests_func(final_url, data=encoded_data, headers=headers, cert=(public_cert, private_cert)) - - else: - resp = requests_func(final_url, headers=headers, cert=(public_cert, private_cert)) - self.send_response(resp.status_code) - for key in resp.headers: - self.send_header(key, resp.headers[key]) - self.end_headers() - try: - self.wfile.write(resp.content) - self.wfile.flush() - except Exception as e: - print("Exception while writing response body:", e) - - - server_address = ('', 8001) - self.httpd = HTTPServer(server_address, ProxyHTTPRequestHandler) - print('proxy server is running') - self.httpd.serve_forever() - - -def exit_now(signum, frame): - sys.exit(0) - -if __name__ == '__main__': - proxy = ApiProxy() - signal.signal(signal.SIGTERM, exit_now) - proxy.start_server() \ No newline at end of file diff --git a/python/digital_signature.py b/python/digital_signature.py new file mode 100755 index 0000000..17b1097 --- /dev/null +++ b/python/digital_signature.py @@ -0,0 +1,4 @@ +import jwt + +def generate_digital_signature(digital_key, body): + return jwt.encode(body, digital_key, algorithm="RS256") diff --git a/python/sample-authentication-code/tests/getJWT_test.py b/python/digital_signature_test.py similarity index 92% rename from python/sample-authentication-code/tests/getJWT_test.py rename to python/digital_signature_test.py index c7ccbda..750b811 100644 --- a/python/sample-authentication-code/tests/getJWT_test.py +++ b/python/digital_signature_test.py @@ -1,8 +1,6 @@ -import sys -sys.path.append('../') import unittest import jwt -from getJWT import generate_digital_signature +from digital_signature import generate_digital_signature from dotenv import load_dotenv import os diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 0000000..db8ed17 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,3 @@ +PyJWT==2.6.0 +python-dotenv==0.21.1 +cryptography==41.0.6 \ No newline at end of file diff --git a/python/sample-authentication-code/.env.example b/python/sample-authentication-code/.env.example deleted file mode 100644 index 14b861d..0000000 --- a/python/sample-authentication-code/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -ACCESS_TOKEN_URL="" -CLIENT_ID="" -CLIENT_SECRET="" \ No newline at end of file diff --git a/python/sample-authentication-code/README.md b/python/sample-authentication-code/README.md deleted file mode 100644 index cda70ca..0000000 --- a/python/sample-authentication-code/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Python snippets - -A collection of scripts for helping you to generate certificates, get access tokens for OAuth and encode your payloads. - -- getAccessToken: This snippet highlights how to obtain an OAuth access token using Python. -- getJWT: This snippet is to show you how to generate a JWT/Digital Signature for sending post requests to our payments APIs. -- generateCertificates: This snippet is used to create a certificate request (CSR) along with a self-signed X509 certificate (CRT). -- sendFirstRequest: This snippet is used to send a request to our servers. -- main: This snippet shows how to send a request to our servers which are protected by OAuth diff --git a/python/sample-authentication-code/generateCertificates.py b/python/sample-authentication-code/generateCertificates.py deleted file mode 100644 index 92edc28..0000000 --- a/python/sample-authentication-code/generateCertificates.py +++ /dev/null @@ -1,65 +0,0 @@ -'''' -This utility script is used to create a certificate request (CSR) along with a self-signed X509 certificate (CRT) using -cryptography which is a python library containing various cryptography utilities to create and handle communicate protocols. - -generateCertificates.js is a script that will ask for various information that is incorporated into your certificate request -which can then be used with an approved certificate authority (CA) to receive a signed certificate to on-board to PROD environment. -The script will also generate a self-signed certificate using basic extensions that can be used to on-board to CAT environment. - -You must include your certificate details in the .env file - -''' - -from cryptography import x509 -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.x509.oid import NameOID -import datetime - -def generate_self_signed_cert(COUNTRY_NAME, STATE_OR_PROVINCE_NAME, LOCALITY_NAME, ORGANIZATION_NAME, COMMON_NAME, DNS_NAME): - # Generate a private key - private_key = rsa.generate_private_key( - public_exponent=65537, - key_size=2048, - backend=default_backend() - ) - - # Create a self-signed certificate - subject = issuer = x509.Name([ - x509.NameAttribute(NameOID.COUNTRY_NAME, COUNTRY_NAME), - x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, STATE_OR_PROVINCE_NAME), - x509.NameAttribute(NameOID.LOCALITY_NAME, LOCALITY_NAME), - x509.NameAttribute(NameOID.ORGANIZATION_NAME,ORGANIZATION_NAME), - x509.NameAttribute(NameOID.COMMON_NAME, COMMON_NAME), - ]) - cert = x509.CertificateBuilder().subject_name( - subject - ).issuer_name( - issuer - ).public_key( - private_key.public_key() - ).serial_number( - x509.random_serial_number() - ).not_valid_before( - datetime.datetime.utcnow() - ).not_valid_after( - # Expires after 365 days - datetime.datetime.utcnow() + datetime.timedelta(days=365) - ).add_extension( - x509.SubjectAlternativeName([x509.DNSName(DNS_NAME)]), - critical=False, - ).sign(private_key, hashes.SHA256(), default_backend()) - - # Write the private key and certificate to files - with open("private_key.pem", "wb") as f: - f.write(private_key.private_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PrivateFormat.TraditionalOpenSSL, - encryption_algorithm=serialization.NoEncryption() - )) - - with open("certificate.pem", "wb") as f: - f.write(cert.public_bytes(serialization.Encoding.PEM)) - - print("Certificate and private key generated successfully.") diff --git a/python/sample-authentication-code/getAccessToken.py b/python/sample-authentication-code/getAccessToken.py deleted file mode 100644 index 1a7693e..0000000 --- a/python/sample-authentication-code/getAccessToken.py +++ /dev/null @@ -1,15 +0,0 @@ -import requests -''' -This snippet highlights how to obtain an OAuth access token using Python. -You will provide your CLIENT_ID, CLIENT_SECRET and ACCESS_TOKEN_URL. -You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start -''' - - -def get_access_token(url, client_id, client_secret): - response = requests.post( - url, - data={"grant_type": "client_credentials", "scope":"jpm:payments:sandbox"}, - auth=(client_id, client_secret), - ) - return response.json()["access_token"] diff --git a/python/sample-authentication-code/getJWT.py b/python/sample-authentication-code/getJWT.py deleted file mode 100755 index 7f9953b..0000000 --- a/python/sample-authentication-code/getJWT.py +++ /dev/null @@ -1,8 +0,0 @@ -''' -This snippet is to show you how to generate a JWT/Digital Signature for sending post requests to our payments APIs. -You will need to provide your signing key and the body you wish to encode. -''' -import jwt - -def generate_digital_signature(digital_key, body): - return jwt.encode(body, digital_key, algorithm="RS256") diff --git a/python/sample-authentication-code/main.py b/python/sample-authentication-code/main.py deleted file mode 100644 index 1a0c154..0000000 --- a/python/sample-authentication-code/main.py +++ /dev/null @@ -1,29 +0,0 @@ -from getAccessToken import get_access_token -from sendFirstRequest import send_first_request -from dotenv import load_dotenv -import os - -load_dotenv() - -''' -This snippet highlights how to access one of our OAuth api's using Python. -First we gather our access token using the code defined in the getAccessToken file. -Then we send the request using the code defined in sendFirstRequest file. -You will provide your CLIENT_ID, CLIENT_SECRET and ACCESS_TOKEN_URL in a .env file. -You will also include your API url for hitting your API. -You can obtain these values following this guide: https://developer.payments.jpmorgan.com/quick-start -''' - -access_token_url=os.getenv('ACCESS_TOKEN_URL') -client_id=os.getenv('CLIENT_ID') -client_secret=os.getenv('CLIENT_SECRET') -api_url = "" - -def main(): - access_token = get_access_token(url=access_token_url, client_id=client_id, client_secret=client_secret) - print('Gathered access token') - response = send_first_request(url=api_url, access_token=access_token) - print(response) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/python/sample-authentication-code/requirements.txt b/python/sample-authentication-code/requirements.txt deleted file mode 100644 index e052558..0000000 --- a/python/sample-authentication-code/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -PyJWT==2.6.0 -python-dotenv==0.21.1 -cryptography==42.0.4 -requests==2.32.0 -requests-oauthlib==1.3.1 -python-dotenv===0.21.1 \ No newline at end of file diff --git a/python/sample-authentication-code/sendFirstRequest.py b/python/sample-authentication-code/sendFirstRequest.py deleted file mode 100644 index 68f7ec1..0000000 --- a/python/sample-authentication-code/sendFirstRequest.py +++ /dev/null @@ -1,16 +0,0 @@ -import requests - -''' -This snippet is used to send a request to our servers. -Combine it with our getAccessToken to get started -''' - -def send_first_request(url, access_token): - headers = { - "Content-Type": "application/json", - "Accept": "application/json", - "Authorization": "Bearer " + access_token - } - response = requests.get(url, headers=headers) - return response.json() - diff --git a/python/sample-authentication-code/tests/generateCertificates_test.py b/python/sample-authentication-code/tests/generateCertificates_test.py deleted file mode 100644 index f8d5572..0000000 --- a/python/sample-authentication-code/tests/generateCertificates_test.py +++ /dev/null @@ -1,39 +0,0 @@ -import sys -sys.path.append('../') - -import unittest -import os -import subprocess -from dotenv import load_dotenv -import os - -# Load environment variables from .env file -load_dotenv() - -COUNTRY_NAME=os.getenv('COUNTRY_NAME') -STATE_OR_PROVINCE_NAME=os.getenv('STATE_OR_PROVINCE_NAME') -LOCALITY_NAME=os.getenv('LOCALITY_NAME') -ORGANIZATION_NAME=os.getenv('ORGANIZATION_NAME') -COMMON_NAME=os.getenv('COMMON_NAME') -DNS_NAME=os.getenv('DNS_NAME') - -# Import the function to be tested -from generateCertificates import generate_self_signed_cert - -class TestGenerateCertificates(unittest.TestCase): - def test_generate_self_signed_cert(self): - # Call the function to generate the certificate - generate_self_signed_cert(COUNTRY_NAME, STATE_OR_PROVINCE_NAME, LOCALITY_NAME, ORGANIZATION_NAME, COMMON_NAME, DNS_NAME) - - # Check if the certificate and private key files are generated - self.assertTrue(os.path.exists("private_key.pem")) - self.assertTrue(os.path.exists("certificate.pem")) - - # Use OpenSSL command to check if the certificate is valid - try: - subprocess.check_output(["openssl", "x509", "-in", "certificate.pem", "-noout", "-checkend", "0"]) - except subprocess.CalledProcessError: - self.fail("Certificate is not valid.") - -if __name__ == '__main__': - unittest.main() diff --git a/python/sample-authentication-code/tests/getAccessToken_test.py b/python/sample-authentication-code/tests/getAccessToken_test.py deleted file mode 100644 index 72fafa5..0000000 --- a/python/sample-authentication-code/tests/getAccessToken_test.py +++ /dev/null @@ -1,37 +0,0 @@ -import sys -sys.path.append('../') -import unittest -from requests.exceptions import RequestException -from unittest.mock import patch, MagicMock -from getAccessToken import get_access_token - -class TestGetAccessToken(unittest.TestCase): - @patch('requests.post') - def test_get_access_token_success(self, mock_post): - # Mocking response object - response_mock = MagicMock() - response_mock.json.return_value = {"access_token": "mock_access_token"} - mock_post.return_value = response_mock - - # Call the function - access_token = get_access_token("mock_url", "mock_client_id", "mock_client_secret") - - # Assertions - mock_post.assert_called_once_with( - "mock_url", - data={"grant_type": "client_credentials", "scope": "jpm:payments:sandbox"}, - auth=("mock_client_id", "mock_client_secret") - ) - self.assertEqual(access_token, "mock_access_token") - - @patch('requests.post') - def test_get_access_token_failure(self, mock_post): - # Mocking response object to raise an exception - mock_post.side_effect = RequestException("Mocked request exception") - - # Call the function - with self.assertRaises(RequestException): - get_access_token("mock_url", "mock_client_id", "mock_client_secret") - -if __name__ == '__main__': - unittest.main() diff --git a/python/sample-authentication-code/tests/sendFirstRequest_test.py b/python/sample-authentication-code/tests/sendFirstRequest_test.py deleted file mode 100644 index 5515dd6..0000000 --- a/python/sample-authentication-code/tests/sendFirstRequest_test.py +++ /dev/null @@ -1,25 +0,0 @@ -import unittest -from unittest.mock import Mock -from sendFirstRequest import send_first_request - -class TestSendFirstRequest(unittest.TestCase): - - def test_send_first_request(self): - # Mocking requests.post method to avoid actual HTTP requests - mock_response = Mock() - mock_response.json.return_value = {"status": "success"} - with unittest.mock.patch('requests.get', return_value=mock_response) as mock_get: - url = "https://example.com/api" - access_token = "your_access_token" - response = send_first_request(url, access_token) - # Assert that requests.post was called with the correct arguments - mock_get.assert_called_once_with(url, headers={ - "Content-Type": "application/json", - "Accept": "application/json", - "Authorization": "Bearer " + access_token - }) - # Assert that the response matches the expected value - self.assertEqual(response, {"status": "success"}) - -if __name__ == '__main__': - unittest.main()