diff --git a/.demos b/.demos
new file mode 100644
index 00000000..0513c04f
--- /dev/null
+++ b/.demos
@@ -0,0 +1,16 @@
+# list of use case demos
+DEMOS=("uc-single-touch-conversion" "uc-remarketing" "uc-vast-video-paapi" "uc-video-multi-seller-seq-auction-paapi")
+
+# For each use case we need their Cloud Function Entry Point
+typeset -A DEMO_MONITORING_ENTRYPOINT
+DEMO_MONITORING_ENTRYPOINT[uc-single-touch-conversion]=MonitorUcSingleTouchConversion
+DEMO_MONITORING_ENTRYPOINT[uc-remarketing]=MonitorUcRemarketing
+DEMO_MONITORING_ENTRYPOINT[uc-vast-video-paapi]=MonitorUcVastVideoPaapi
+DEMO_MONITORING_ENTRYPOINT[uc-video-multi-seller-seq-auction-paapi]=MonitorUcVideoMultiSellerSeqAuctionPaapi
+
+# For each use case we need to define the Synethtic Monitor Title
+typeset -A DEMO_TITLE
+DEMO_TITLE[uc-single-touch-conversion]="Single-touch conversion Attribution"
+DEMO_TITLE[uc-remarketing]="Remarketing"
+DEMO_TITLE[uc-vast-video-paapi]="Instream VAST video ad in a Protected Audience single-seller auction"
+DEMO_TITLE[uc-video-multi-seller-seq-auction-paapi]="Instream video ad in a Protected Audience multi-seller sequential auction setup"
diff --git a/.env b/.env
index 58e646f2..fea6c5fc 100644
--- a/.env
+++ b/.env
@@ -5,28 +5,37 @@ EXTERNAL_PORT=443
PORT=8080
# list of service names
-SERVICES=("home" "news" "shop" "travel" "dsp" "dsp-a" "dsp-b" "ssp" "ssp-a" "ssp-b" "idp" "topics" "topics-server" "ad-server")
+SERVICES=("home" "news" "shop" "travel" "dsp" "dsp-a" "dsp-b" "ssp" "ssp-a" "ssp-b" "idp" "ad-server")
+
+DEMO_HOST_PREFIX=privacy-sandbox-demos-
# home
HOME_HOST=privacy-sandbox-demos-home.dev
+HOME_URI=http://privacy-sandbox-demos-home.dev:8080
HOME_TOKEN=""
HOME_DETAIL="Home page of Privacy Sandbox Demos"
+# Measurement ID for Google Analytics
+HOME_MEASUREMENT_ID="G-12345ABCDE"
+# Container ID for Google Tag Manager
+HOME_TAG_CONTAINER_ID="GTM-12345ABC"
# Publisher
## news
NEWS_HOST=privacy-sandbox-demos-news.dev
+NEWS_URI=http://privacy-sandbox-demos-news.dev:8080
NEWS_TOKEN=""
NEWS_DETAIL="Publisher: News media site"
-
# Advertizer
## shop
SHOP_HOST=privacy-sandbox-demos-shop.dev
+SHOP_URI=http://privacy-sandbox-demos-shop.dev:8080
SHOP_TOKEN=""
SHOP_DETAIL="Advertiser: EC shopping site"
## travel
TRAVEL_HOST=privacy-sandbox-demos-travel.dev
+TRAVEL_URI=http://privacy-sandbox-demos-travel.dev:8080
TRAVEL_TOKEN=""
TRAVEL_DETAIL="Advertiser: EC travel site"
@@ -78,16 +87,14 @@ IDP_DETAIL="Identity Provider for relying parties. Also Issuing Private State To
## Topics related
## site to observe topics
-TOPICS_MOTO_HOST=motorcycles.privacy-sandbox-demos-news.dev
-TOPICS_SOCCER_HOST=soccer.privacy-sandbox-demos-news.dev
-TOPICS_GARDENING_HOST=gardening.privacy-sandbox-demos-news.dev
+MOTO_NEWS_HOST=motorcycles.privacy-sandbox-demos-news.dev
+MOTO_NEWS_URI=http://motorcycles.privacy-sandbox-demos-news.dev:8080
+SOCCER_NEWS_HOST=soccer.privacy-sandbox-demos-news.dev
+SOCCER_NEWS_URI=http://soccer.privacy-sandbox-demos-news.dev:8080
+GARDENING_NEWS_HOST=gardening.privacy-sandbox-demos-news.dev
+GARDENING_NEWS_URI=http://gardening.privacy-sandbox-demos-news.dev:8080
TOPICS_DETAIL="Topics page"
-## server to request topics with headers
-TOPICS_SERVER_HOST=topics-server.privacy-sandbox-demos-news.dev
-TOPICS_SERVER_URI=http://topics-server.privacy-sandbox-demos-news.dev:8080
-TOPICS_SERVER_DETAIL="Topics server"
-
## ad server
AD_SERVER_HOST=privacy-sandbox-demos-ad-server.dev
AD_SERVER_URI=http://privacy-sandbox-demos-ad-server.dev:8080
diff --git a/.env.deploy.template b/.env.deploy.template
index a5793000..d6edaf4d 100644
--- a/.env.deploy.template
+++ b/.env.deploy.template
@@ -1,3 +1,5 @@
-# Deployment
+# Deployment env vars used by shell scripts
GCP_PROJECT_NAME=
-FIREBASE_HOSTING_DOMAIN=
\ No newline at end of file
+FIREBASE_HOSTING_DOMAIN=
+GCP_REGION=us-central1
+ENV_FILE=cicd/.env.dev
diff --git a/.gcloudignore b/.gcloudignore
index 661eadd1..2e015eae 100644
--- a/.gcloudignore
+++ b/.gcloudignore
@@ -1,13 +1,7 @@
# ref : https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore
-#!include:.gitignore
-
.gcloudignore
.git
.gitignore
-services/home/.docusaurus
-services/shop/.next
-# include services/home/build/* files into `gcloud builds submit` command
-# DEPRECATED as we now build html files with ci/cd
-# !services/home/build
+#!include:.gitignore
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 5e5c868f..2b5ad2aa 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -85,57 +85,3 @@ updates:
prefix: "[home] "
include: "scope"
open-pull-requests-limit: 3
- - package-ecosystem: npm
- directory: "/services/dsp"
- schedule:
- interval: "monthly"
- rebase-strategy: disabled
- commit-message:
- prefix: "[dsp] "
- include: "scope"
- open-pull-requests-limit: 3
- - package-ecosystem: npm
- directory: "/services/ssp"
- schedule:
- interval: "monthly"
- rebase-strategy: disabled
- commit-message:
- prefix: "[ssp] "
- include: "scope"
- open-pull-requests-limit: 3
- - package-ecosystem: npm
- directory: "/services/news"
- schedule:
- interval: "monthly"
- rebase-strategy: disabled
- commit-message:
- prefix: "[news] "
- include: "scope"
- open-pull-requests-limit: 3
- - package-ecosystem: npm
- directory: "/services/shop"
- schedule:
- interval: "monthly"
- rebase-strategy: disabled
- commit-message:
- prefix: "[shop] "
- include: "scope"
- open-pull-requests-limit: 3
- - package-ecosystem: npm
- directory: "/services/travel"
- schedule:
- interval: "monthly"
- rebase-strategy: disabled
- commit-message:
- prefix: "[travel] "
- include: "scope"
- open-pull-requests-limit: 3
- - package-ecosystem: gomod
- directory: "/services/collector/src"
- schedule:
- interval: "monthly"
- rebase-strategy: disabled
- commit-message:
- prefix: "[collector] "
- include: "scope"
- open-pull-requests-limit: 3
diff --git a/.github/workflows/github-repo-stats.yml b/.github/workflows/github-repo-stats.yml
new file mode 100644
index 00000000..fb130a1b
--- /dev/null
+++ b/.github/workflows/github-repo-stats.yml
@@ -0,0 +1,19 @@
+name: github-repo-stats
+
+on:
+ schedule:
+ # Run this once per day, towards the end of the day for keeping the most
+ # recent data point most meaningful (hours are interpreted in UTC).
+ - cron: "0 23 * * *"
+ workflow_dispatch: # Allow for running this manually.
+
+jobs:
+ j1:
+ name: github-repo-stats
+ runs-on: ubuntu-latest
+ steps:
+ - name: run-ghrs
+ # Use latest release.
+ uses: jgehrcke/github-repo-stats@RELEASE
+ with:
+ ghtoken: ${{ secrets.ghrs_github_api_token }}
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
index 1fb9302a..98bf9864 100644
--- a/.github/workflows/scorecard.yml
+++ b/.github/workflows/scorecard.yml
@@ -51,7 +51,7 @@ jobs:
# uploads of run results in SARIF format to the repository Actions tab.
# https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts
- name: "Upload artifact"
- uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
+ uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
with:
name: SARIF file
path: results.sarif
@@ -60,6 +60,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard (optional).
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10
+ uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
with:
sarif_file: results.sarif
diff --git a/.gitignore b/.gitignore
index 0e8608d9..ed9a7f12 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,4 @@ build
*pem
.firebase
.firebaserc
-.env.deploy
\ No newline at end of file
+.env.deploy
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 701d86b2..625d9a3b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -32,7 +32,7 @@ repos:
- yaml
- repo: https://github.com/DavidAnson/markdownlint-cli2
- rev: v0.13.0
+ rev: v0.17.1
hooks:
- id: markdownlint-cli2
name: lint markdown
diff --git a/README.md b/README.md
index 121626e3..23c42af8 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Privacy Sandbox Demos
-A use case demo library for [Privacy Sandbox APIs](https://developer.chrome.com/en/docs/privacy-sandbox/) on the web.
+A use case demo library for the [Privacy Sandbox APIs](https://developer.chrome.com/en/docs/privacy-sandbox/) on the web.
## Motivation
@@ -25,6 +25,7 @@ This repository contains :
- Deployment scripts
- [Instructions for deploying and running the demos in your local environment with Docker](docs/deploy-to-linux-docker.md)
- [Instructions for deploying and running the demos on Google Cloud Platform](docs/deploy-to-gcp.md)
+- [A list of codebase dependencies to prepare for development](docs/dependencies.md)
- Development framework to contribute to the project
If you are a developer we recommend you follow the [deployment instructions](docs/deploy-to-linux-docker.md). If you are simply curious, we recommend
@@ -34,12 +35,13 @@ you have a look at our [Google-hosted instances](https://privacy-sandbox-demos.d
The current release supports the following use cases:
-| **Category** | **Use Case** | **Privacy Sandbox APIs** | **Relevant for** |
-| :---------------------------: | :-------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------: | :----------------------------------------: |
-| Show Relevant Video Ads | [Instream VAST video ad in a Protected Audience multi-seller auction](services/home/docs/demos/instream-video-ad-multi-seller.md) | Protected Audience API | Publisher, Ad Server, SSP, Advertiser, DSP |
-| Show Relevant Video Ads | [Instream VAST video ad in a Protected Audience single-seller auction](services/home/docs/demos/vast-video-protected-audience.md) | Protected Audience API | Publisher, SSP, Advertiser, DSP |
-| Show Relevant Content and Ads | [Retargeting / Remarketing](services/home/docs/demos/retargeting-remarketing.md) | Protected Audience API | Publisher, SSP, Advertiser, DSP |
-| Measure Digital Ads | [Single-touch conversion Attribution](services/home/docs/demos/single-touch-conversion-attribution.md) | Attribution Reporting API, Aggregation Service | Publisher, SSP, Advertiser, DSP |
+| **Category** | **Use Case** | **Privacy Sandbox APIs** | **Relevant for** |
+| :---------------------------: | :-------------------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------: | :----------------------------------------: |
+| Show Relevant Video Ads | [Instream VAST video ad in a Protected Audience multi-seller auction](services/home/docs/demos/instream-video-ad-multi-seller.md) | Protected Audience API | Publisher, Ad Server, SSP, Advertiser, DSP |
+| Show Relevant Video Ads | [Instream VAST video ad in a Protected Audience single-seller auction](services/home/docs/demos/vast-video-protected-audience.md) | Protected Audience API | Publisher, SSP, Advertiser, DSP |
+| Show Relevant Content and Ads | [Retargeting / Remarketing](services/home/docs/demos/retargeting-remarketing.md) | Protected Audience API | Publisher, SSP, Advertiser, DSP |
+| Measure Digital Ads | [Single-touch conversion Attribution](services/home/docs/demos/single-touch-conversion-attribution.md) | Attribution Reporting API, Aggregation Service | Publisher, SSP, Advertiser, DSP |
+| Measure Digital Ads | [Multi-touch conversion Attribution](services/home/docs/demos/multi-touch-conversion-attribution.md) | Private Aggregation, Shared Storage, Aggregation Service | Publisher, Advertiser, DSP |
These use cases are based on a set of demo apps and services that we have developed to simulate the actors in the ad tech ecosystem :
diff --git a/cicd/.env.dev b/cicd/.env.dev
index f9e5e20e..01a262fe 100644
--- a/cicd/.env.dev
+++ b/cicd/.env.dev
@@ -5,16 +5,24 @@ EXTERNAL_PORT=443
PORT=8080
# list of service names
-SERVICES=("home" "news" "shop" "travel" "dsp" "dsp-a" "dsp-b" "ssp" "ssp-a" "ssp-b" "idp" "topics" "topics-server" "ad-server")
+SERVICES=("home" "news" "shop" "travel" "dsp" "dsp-a" "dsp-b" "ssp" "ssp-a" "ssp-b" "idp" "ad-server")
+
+DEMO_HOST_PREFIX=privacy-sandcastle-dev-
# home
HOME_HOST=privacy-sandcastle-dev-home.web.app
+HOME_URI=https://privacy-sandcastle-dev-home.web.app
HOME_TOKEN=""
HOME_DETAIL="Home page of Privacy Sandbox Demos"
+# Measurement ID for Google Analytics
+HOME_MEASUREMENT_ID="G-6V8T201H6F"
+# Container ID for Google Tag Manager
+HOME_TAG_CONTAINER_ID="GTM-5BJSXX2D"
# Publisher
## news
NEWS_HOST=privacy-sandcastle-dev-news.web.app
+NEWS_URI=https://privacy-sandcastle-dev-news.web.app
NEWS_TOKEN=""
NEWS_DETAIL="Publisher: News media site"
@@ -22,11 +30,13 @@ NEWS_DETAIL="Publisher: News media site"
# Advertizer
## shop
SHOP_HOST=privacy-sandcastle-dev-shop.web.app
+SHOP_URI=https://privacy-sandcastle-dev-shop.web.app
SHOP_TOKEN=""
SHOP_DETAIL="Advertiser: EC shopping site"
## travel
TRAVEL_HOST=privacy-sandcastle-dev-travel.web.app
+TRAVEL_URI=https://privacy-sandcastle-dev-travel.web.app
TRAVEL_TOKEN=""
TRAVEL_DETAIL="Advertiser: EC travel site"
@@ -35,7 +45,7 @@ TRAVEL_DETAIL="Advertiser: EC travel site"
## dsp
DSP_HOST=privacy-sandcastle-dev-dsp.web.app
DSP_URI=https://privacy-sandcastle-dev-dsp.web.app
-DSP_TOKEN="A0nDunxZWFAhYvrWCRTblhlyK3D9m0czMNY/m9t2+pG3i1JHkMDasm8m66CwZS54qMeOepb+d9DYjawtBDbDrQgAAACYeyJvcmlnaW4iOiJodHRwczovL3ByaXZhY3ktc2FuZGNhc3RsZS1kZXYtZHNwLndlYi5hcHA6NDQzIiwiZmVhdHVyZSI6IlByaXZhY3lTYW5kYm94QWRzQVBJcyIsImV4cGlyeSI6MTY5NTE2Nzk5OSwiaXNTdWJkb21haW4iOnRydWUsImlzVGhpcmRQYXJ0eSI6dHJ1ZX0="
+DSP_TOKEN=""
DSP_DETAIL="Ad-Platform: DSP for advertiser"
DSP_A_HOST=privacy-sandcastle-dev-dsp-a1.web.app
@@ -51,7 +61,7 @@ DSP_B_DETAIL="Ad-Platform: DSP-B for advertiser"
## ssp
SSP_HOST=privacy-sandcastle-dev-ssp.web.app
SSP_URI=https://privacy-sandcastle-dev-ssp.web.app
-SSP_TOKEN="A3Jo3gcicBIWHTI+QzCeb2h+B4TJX/y8PSngoHtoHeCpnRi2Ny/TFjJ/QtSQhBeS+2x43Jtd5GfksanOOglcVgIAAACYeyJvcmlnaW4iOiJodHRwczovL3ByaXZhY3ktc2FuZGNhc3RsZS1kZXYtc3NwLndlYi5hcHA6NDQzIiwiZmVhdHVyZSI6IlByaXZhY3lTYW5kYm94QWRzQVBJcyIsImV4cGlyeSI6MTY5NTE2Nzk5OSwiaXNTdWJkb21haW4iOnRydWUsImlzVGhpcmRQYXJ0eSI6dHJ1ZX0="
+SSP_TOKEN=""
SSP_DETAIL="Ad-Platform: SSP for publisher"
SSP_A_HOST=privacy-sandcastle-dev-ssp-a.web.app
@@ -78,16 +88,14 @@ IDP_DETAIL="Identity Provider for relying parties. Also Issuing Private State To
## Topics related
## site to observe topics
-TOPICS_MOTO_HOST=privacy-sandcastle-dev-motorcycles.web.app
-TOPICS_SOCCER_HOST=privacy-sandcastle-dev-soccer-foot.web.app
-TOPICS_GARDENING_HOST=privacy-sandcastle-dev-gardening-potager.web.app
+MOTO_NEWS_HOST=privacy-sandcastle-dev-motorcycles.web.app
+MOTO_NEWS_URI=https://privacy-sandcastle-dev-motorcycles.web.app
+SOCCER_NEWS_HOST=privacy-sandcastle-dev-soccer-foot.web.app
+SOCCER_NEWS_URI=https://privacy-sandcastle-dev-soccer-foot.web
+GARDENING_NEWS_HOST=privacy-sandcastle-dev-gardening-potager.web.app
+GARDENING_NEWS_URI=https://privacy-sandcastle-dev-gardening-potager
TOPICS_DETAIL="Topics page"
-## server to request topics with headers
-TOPICS_SERVER_HOST=privacy-sandcastle-dev-topics-server.web.app
-TOPICS_SERVER_URI=https://privacy-sandcastle-dev-topics-server.web.app
-TOPICS_SERVER_DETAIL="Topics server"
-
## ad server
AD_SERVER_HOST=privacy-sandcastle-dev-ad-server.web.app
AD_SERVER_URI=https://privacy-sandcastle-dev-ad-server.web.app
diff --git a/cicd/.env.prod b/cicd/.env.prod
index ada35e55..7283ba03 100644
--- a/cicd/.env.prod
+++ b/cicd/.env.prod
@@ -5,16 +5,24 @@ EXTERNAL_PORT=443
PORT=8080
# list of service names
-SERVICES=("home" "news" "shop" "travel" "dsp" "dsp-a" "dsp-b" "ssp" "ssp-a" "ssp-b" "idp" "topics" "topics-server" "ad-server")
+SERVICES=("home" "news" "shop" "travel" "dsp" "dsp-a" "dsp-b" "ssp" "ssp-a" "ssp-b" "idp" "ad-server")
+
+DEMO_HOST_PREFIX=privacy-sandbox-demos-
# home
-HOME_HOST=privacy-sandbox-demos-home.dev
+HOME_HOST=privacy-sandbox-demos.dev
+HOME_URI=https://privacy-sandbox-demos.dev
HOME_TOKEN=""
HOME_DETAIL="Home page of Privacy Sandbox Demos"
+# Measurement ID for Google Analytics
+HOME_MEASUREMENT_ID="G-2M6L90WK9X"
+# Container ID for Google Tag Manager
+HOME_TAG_CONTAINER_ID="GTM-TNT5ND8K"
# Publisher
## news
NEWS_HOST=privacy-sandbox-demos-news.dev
+NEWS_URI=https://privacy-sandbox-demos-news.dev
NEWS_TOKEN=""
NEWS_DETAIL="Publisher: News media site"
@@ -22,11 +30,13 @@ NEWS_DETAIL="Publisher: News media site"
# Advertizer
## shop
SHOP_HOST=privacy-sandbox-demos-shop.dev
+SHOP_URI=https://privacy-sandbox-demos-shop.dev
SHOP_TOKEN=""
SHOP_DETAIL="Advertiser: EC shopping site"
## travel
TRAVEL_HOST=privacy-sandbox-demos-travel.dev
+TRAVEL_URI=https://privacy-sandbox-demos-travel.dev
TRAVEL_TOKEN=""
TRAVEL_DETAIL="Advertiser: EC travel site"
@@ -78,16 +88,14 @@ IDP_DETAIL="Identity Provider for relying parties. Also Issuing Private State To
## Topics related
## site to observe topics
-TOPICS_MOTO_HOST=motorcycles.privacy-sandbox-demos-news.dev
-TOPICS_SOCCER_HOST=soccer.privacy-sandbox-demos-news.dev
-TOPICS_GARDENING_HOST=gardening.privacy-sandbox-demos-news.dev
+MOTO_NEWS_HOST=motorcycles.privacy-sandbox-demos-news.dev
+MOTO_NEWS_URI=https://motorcycles.privacy-sandbox-demos-news.dev
+SOCCER_NEWS_HOST=soccer.privacy-sandbox-demos-news.dev
+SOCCER_NEWS_URI=https://soccer.privacy-sandbox-demos-news.dev
+GARDENING_NEWS_HOST=gardening.privacy-sandbox-demos-news.dev
+GARDENING_NEWS_URI=https://gardening.privacy-sandbox-demos-news.dev
TOPICS_DETAIL="Topics page"
-## server to request topics with headers
-TOPICS_SERVER_HOST=topics-server.privacy-sandbox-demos-news.dev
-TOPICS_SERVER_URI=https://topics-server.privacy-sandbox-demos-news.dev
-TOPICS_SERVER_DETAIL="Topics server"
-
## ad server
AD_SERVER_HOST=privacy-sandbox-demos-ad-server.dev
AD_SERVER_URI=https://privacy-sandbox-demos-ad-server.dev
diff --git a/cicd/cloudbuild.yaml b/cicd/cloudbuild.yaml
index aea5c976..71ea43ef 100644
--- a/cicd/cloudbuild.yaml
+++ b/cicd/cloudbuild.yaml
@@ -19,124 +19,7 @@ steps:
- "PROJECT_ENV=$_PROJECT_ENV"
script: |
#!/usr/bin/env bash
-
- cp -f cicd/attestations/privacy-sandbox-attestations.json.dsp.${PROJECT_ENV} services/dsp/src/public/.well-known/privacy-sandbox-attestations.json
- cp -f cicd/attestations/privacy-sandbox-attestations.json.dsp-a.${PROJECT_ENV} services/dsp-a/src/public/.well-known/privacy-sandbox-attestations.json
- cp -f cicd/attestations/privacy-sandbox-attestations.json.dsp-b.${PROJECT_ENV} services/dsp-b/src/public/.well-known/privacy-sandbox-attestations.json
- cp -f cicd/attestations/privacy-sandbox-attestations.json.ssp.${PROJECT_ENV} services/ssp/src/public/.well-known/privacy-sandbox-attestations.json
- cp -f cicd/attestations/privacy-sandbox-attestations.json.ssp-a.${PROJECT_ENV} services/ssp-a/src/public/.well-known/privacy-sandbox-attestations.json
- cp -f cicd/attestations/privacy-sandbox-attestations.json.ssp-b.${PROJECT_ENV} services/ssp-b/src/public/.well-known/privacy-sandbox-attestations.json
- cp -f cicd/attestations/privacy-sandbox-attestations.json.ad-server.${PROJECT_ENV} services/ad-server/src/public/.well-known/privacy-sandbox-attestations.json
- # DSP
- # Build the container image
- - name: "gcr.io/cloud-builders/docker"
- id: build-dsp
- waitFor:
- - copy-attestations
- args:
- [
- "build",
- "-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp:$COMMIT_SHA",
- "services/dsp",
- ]
- # Push the container image to Container Registry
- - name: "gcr.io/cloud-builders/docker"
- id: push-dsp
- waitFor:
- - build-dsp
- args:
- [
- "push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp:$COMMIT_SHA",
- ]
- # Deploy container image to Cloud Run
- - name: "gcr.io/cloud-builders/gcloud"
- id: deploy-dsp
- waitFor:
- - push-dsp
- - read-env
- entrypoint: "bash"
- args:
- - "-c"
- - |
- ENV_VARS=$(cat /workspace/env_vars.txt)
- echo $${ENV_VARS}
- gcloud run deploy dsp --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
-
- # DSP-A
- # Build the container image
- - name: "gcr.io/cloud-builders/docker"
- id: build-dsp-a
- waitFor:
- - copy-attestations
- args:
- [
- "build",
- "-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp-a:$COMMIT_SHA",
- "services/dsp-a",
- ]
- # Push the container image to Container Registry
- - name: "gcr.io/cloud-builders/docker"
- id: push-dsp-a
- waitFor:
- - build-dsp-a
- args:
- [
- "push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp-a:$COMMIT_SHA",
- ]
- # Deploy container image to Cloud Run
- - name: "gcr.io/cloud-builders/gcloud"
- id: deploy-dsp-a
- waitFor:
- - push-dsp-a
- - read-env
- entrypoint: "bash"
- args:
- - "-c"
- - |
- ENV_VARS=$(cat /workspace/env_vars.txt)
- echo $${ENV_VARS}
- gcloud run deploy dsp-a --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp-a:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
-
- # DSP-B
- # Build the container image
- - name: "gcr.io/cloud-builders/docker"
- id: build-dsp-b
- waitFor:
- - copy-attestations
- args:
- [
- "build",
- "-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp-b:$COMMIT_SHA",
- "services/dsp-b",
- ]
- # Push the container image to Container Registry
- - name: "gcr.io/cloud-builders/docker"
- id: push-dsp-b
- waitFor:
- - build-dsp-b
- args:
- [
- "push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp-b:$COMMIT_SHA",
- ]
- # Deploy container image to Cloud Run
- - name: "gcr.io/cloud-builders/gcloud"
- id: deploy-dsp-b
- waitFor:
- - push-dsp-b
- - read-env
- entrypoint: "bash"
- args:
- - "-c"
- - |
- ENV_VARS=$(cat /workspace/env_vars.txt)
- echo $${ENV_VARS}
- gcloud run deploy dsp-b --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp-b:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+ cp -f cicd/attestations/privacy-sandbox-attestations.json.*.${PROJECT_ENV} services/ad-tech/src/public/.well-known/
# HOME
# Build the HTML files with docusaurus
@@ -145,12 +28,21 @@ steps:
waitFor: ["-"]
entrypoint: "npm"
args: ["--prefix", "services/home", "install"]
+
- name: "node"
id: npm-run-build-home
waitFor:
- npm-install-home
- entrypoint: "npm"
- args: ["--prefix", "services/home", "run", "build"]
+ entrypoint: "bash"
+ args:
+ - "-c"
+ - |
+ source cicd/.env.${_PROJECT_ENV}
+ export HOME_HOST
+ export HOME_MEASUREMENT_ID
+ export HOME_TAG_CONTAINER_ID
+ npm --prefix services/home run build
+
# Build the container image
- name: "gcr.io/cloud-builders/docker"
id: build-home
@@ -163,6 +55,7 @@ steps:
"${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/home:$COMMIT_SHA",
"services/home",
]
+
# Push the container image to Container Registry
- name: "gcr.io/cloud-builders/docker"
id: push-home
@@ -173,6 +66,7 @@ steps:
"push",
"${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/home:$COMMIT_SHA",
]
+
# Deploy container image to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
id: deploy-home
@@ -184,8 +78,11 @@ steps:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "HOME_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
gcloud run deploy home --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/home:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+
# NEWS
# Build the container image
- name: "gcr.io/cloud-builders/docker"
@@ -219,6 +116,8 @@ steps:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "NEWS_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
gcloud run deploy news --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/news:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
@@ -255,279 +154,198 @@ steps:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "SHOP_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
gcloud run deploy shop --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/shop:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --session-affinity --set-env-vars "^@^$${ENV_VARS}"
- # SSP
+ # TRAVEL
# Build the container image
- name: "gcr.io/cloud-builders/docker"
- id: build-ssp
- waitFor:
- - copy-attestations
+ id: build-travel
+ waitFor: ["-"]
args:
[
"build",
"-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp:$COMMIT_SHA",
- "services/ssp",
+ "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/travel:$COMMIT_SHA",
+ "services/travel",
]
# Push the container image to Container Registry
- name: "gcr.io/cloud-builders/docker"
- id: push-ssp
+ id: push-travel
waitFor:
- - build-ssp
+ - build-travel
args:
[
"push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp:$COMMIT_SHA",
+ "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/travel:$COMMIT_SHA",
]
# Deploy container image to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
- id: deploy-ssp
+ id: deploy-travel
waitFor:
- - push-ssp
+ - push-travel
- read-env
entrypoint: "bash"
args:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "TRAVEL_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
- gcloud run deploy ssp --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+ gcloud run deploy travel --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/travel:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
- # SSP-A
- # Build the container image
+ # AD-TECH
+ # Build the ad-tech image
- name: "gcr.io/cloud-builders/docker"
- id: build-ssp-a
+ id: build-ad-tech
waitFor:
- copy-attestations
args:
[
"build",
"-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp-a:$COMMIT_SHA",
- "services/ssp-a",
+ "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA",
+ "services/ad-tech",
]
# Push the container image to Container Registry
- name: "gcr.io/cloud-builders/docker"
- id: push-ssp-a
+ id: push-ad-tech
waitFor:
- - build-ssp-a
+ - build-ad-tech
args:
[
"push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp-a:$COMMIT_SHA",
+ "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA",
]
+
+ # DSP
# Deploy container image to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
- id: deploy-ssp-a
+ id: deploy-dsp
waitFor:
- - push-ssp-a
+ - push-ad-tech
- read-env
entrypoint: "bash"
args:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "DSP_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
- gcloud run deploy ssp-a --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp-a:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+ gcloud run deploy dsp --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --command npm --args=run,start,--service=dsp,--project_env=${_PROJECT_ENV} --set-env-vars "^@^$${ENV_VARS}"
- # SSP-B
- # Build the container image
- - name: "gcr.io/cloud-builders/docker"
- id: build-ssp-b
- waitFor:
- - copy-attestations
- args:
- [
- "build",
- "-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp-b:$COMMIT_SHA",
- "services/ssp-b",
- ]
- # Push the container image to Container Registry
- - name: "gcr.io/cloud-builders/docker"
- id: push-ssp-b
- waitFor:
- - build-ssp-b
- args:
- [
- "push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp-b:$COMMIT_SHA",
- ]
+ # DSP-A
# Deploy container image to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
- id: deploy-ssp-b
+ id: deploy-dsp-a
waitFor:
- - push-ssp-b
+ - push-ad-tech
- read-env
entrypoint: "bash"
args:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "DSP_A_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
- gcloud run deploy ssp-b --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp-b:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+ gcloud run deploy dsp-a --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --command npm --args=run,start,--service=dsp-a,--project_env=${_PROJECT_ENV} --set-env-vars "^@^$${ENV_VARS}"
- # TRAVEL
- # Build the container image
- - name: "gcr.io/cloud-builders/docker"
- id: build-travel
- waitFor: ["-"]
- args:
- [
- "build",
- "-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/travel:$COMMIT_SHA",
- "services/travel",
- ]
- # Push the container image to Container Registry
- - name: "gcr.io/cloud-builders/docker"
- id: push-travel
- waitFor:
- - build-travel
- args:
- [
- "push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/travel:$COMMIT_SHA",
- ]
+ # DSP-B
# Deploy container image to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
- id: deploy-travel
+ id: deploy-dsp-b
waitFor:
- - push-travel
+ - push-ad-tech
- read-env
entrypoint: "bash"
args:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "DSP_B_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
- gcloud run deploy travel --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/travel:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+ gcloud run deploy dsp-b --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --command npm --args=run,start,--service=dsp-b,--project_env=${_PROJECT_ENV} --set-env-vars "^@^$${ENV_VARS}"
- # TOPICS
- # Build the container image
- - name: "gcr.io/cloud-builders/docker"
- id: build-topics
- waitFor: ["-"]
- args:
- [
- "build",
- "-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/topics:$COMMIT_SHA",
- "services/topics",
- ]
- # Push the container image to Container Registry
- - name: "gcr.io/cloud-builders/docker"
- id: push-topics
- waitFor:
- - build-topics
- args:
- [
- "push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/topics:$COMMIT_SHA",
- ]
+ # SSP
# Deploy container image to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
- id: deploy-topics
+ id: deploy-ssp
waitFor:
- - push-topics
+ - push-ad-tech
- read-env
entrypoint: "bash"
args:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "SSP_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
- gcloud run deploy topics --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/topics:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+ gcloud run deploy ssp --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --command npm --args=run,start,--service=ssp,--project_env=${_PROJECT_ENV} --set-env-vars "^@^$${ENV_VARS}"
- # TOPICS-SERVER
- # Build the container image
- - name: "gcr.io/cloud-builders/docker"
- id: build-topics-server
- waitFor: ["-"]
- args:
- [
- "build",
- "-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/topics-server:$COMMIT_SHA",
- "services/topics-server",
- ]
- # Push the container image to Container Registry
- - name: "gcr.io/cloud-builders/docker"
- id: push-topics-server
+ # SSP-A
+ # Deploy container image to Cloud Run
+ - name: "gcr.io/cloud-builders/gcloud"
+ id: deploy-ssp-a
waitFor:
- - build-topics-server
+ - push-ad-tech
+ - read-env
+ entrypoint: "bash"
args:
- [
- "push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/topics-server:$COMMIT_SHA",
- ]
+ - "-c"
+ - |
+ ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "SSP_A_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
+ echo $${ENV_VARS}
+ gcloud run deploy ssp-a --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --command npm --args=run,start,--service=ssp-a,--project_env=${_PROJECT_ENV} --set-env-vars "^@^$${ENV_VARS}"
+
+ # SSP-B
# Deploy container image to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
- id: deploy-topics-server
+ id: deploy-ssp-b
waitFor:
- - push-topics-server
+ - push-ad-tech
- read-env
entrypoint: "bash"
args:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "SSP_B_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
- gcloud run deploy topics-server --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/topics-server:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+ gcloud run deploy ssp-b --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --command npm --args=run,start,--service=ssp-b,--project_env=${_PROJECT_ENV} --set-env-vars "^@^$${ENV_VARS}"
# AD-SERVER
- # Build the container image
- - name: "gcr.io/cloud-builders/docker"
- id: build-ad-server
- waitFor:
- - copy-attestations
- args:
- [
- "build",
- "-t",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-server:$COMMIT_SHA",
- "services/ad-server",
- ]
- # Push the container image to Container Registry
- - name: "gcr.io/cloud-builders/docker"
- id: push-ad-server
- waitFor:
- - build-ad-server
- args:
- [
- "push",
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-server:$COMMIT_SHA",
- ]
# Deploy container image to Cloud Run
- name: "gcr.io/cloud-builders/gcloud"
id: deploy-ad-server
waitFor:
- - push-ad-server
+ - push-ad-tech
- read-env
entrypoint: "bash"
args:
- "-c"
- |
ENV_VARS=$(cat /workspace/env_vars.txt)
+ HOSTNAME_ENV="HOSTNAME=$(grep "AD_SERVER_HOST=" cicd/.env.${_PROJECT_ENV} | cut -d '=' -f2)"
+ ENV_VARS=$${HOSTNAME_ENV}@$${ENV_VARS}
echo $${ENV_VARS}
- gcloud run deploy ad-server --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-server:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --set-env-vars "^@^$${ENV_VARS}"
+ gcloud run deploy ad-server --image ${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA --platform managed --region ${_LOCATION} --memory 2Gi --min-instances 1 --allow-unauthenticated --command npm --args=run,start,--service=ad-server,--project_env=${_PROJECT_ENV} --set-env-vars "^@^$${ENV_VARS}"
images:
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp:$COMMIT_SHA"
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp-a:$COMMIT_SHA"
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/dsp-b:$COMMIT_SHA"
+ - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-tech:$COMMIT_SHA"
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/home:$COMMIT_SHA"
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/news:$COMMIT_SHA"
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/shop:$COMMIT_SHA"
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp:$COMMIT_SHA"
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp-a:$COMMIT_SHA"
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ssp-b:$COMMIT_SHA"
- "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/travel:$COMMIT_SHA"
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/topics:$COMMIT_SHA"
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/topics-server:$COMMIT_SHA"
- - "${_LOCATION}-docker.pkg.dev/$PROJECT_ID/${_REPOSITORY}/ad-server:$COMMIT_SHA"
options:
machineType: "E2_HIGHCPU_8"
diff --git a/docker-compose.yml b/docker-compose.yml
index 2e6b8534..c639bcc2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,5 +1,3 @@
-version: "3.8"
-
volumes:
home_node_modules:
news_node_modules:
@@ -9,11 +7,8 @@ volumes:
dsp_a_node_modules:
dsp_b_node_modules:
ssp_node_modules:
- ssp_top_node_modules:
ssp_a_node_modules:
ssp_b_node_modules:
- topics_node_modules:
- topics-server_node_modules:
ad_server_node_modules:
services:
@@ -67,92 +62,92 @@ services:
- adnetwork
dsp:
- image: gcr.io/privacy-sandbox-demos/dsp:latest
- build: ./services/dsp
+ image: gcr.io/privacy-sandbox-demos/ad-tech:latest
+ build: ./services/ad-tech
container_name: "sandcastle_dsp"
hostname: ${DSP_HOST:?err}
env_file:
- .env
volumes:
- - ./services/dsp:/workspace
+ - ./services/ad-tech:/workspace
- dsp_node_modules:/workspace/node_modules
networks:
- adnetwork
dsp-a:
- image: gcr.io/privacy-sandbox-demos/dsp-a:latest
- build: ./services/dsp-a
+ image: gcr.io/privacy-sandbox-demos/ad-tech:latest
+ build: ./services/ad-tech
container_name: "sandcastle_dsp_a"
hostname: ${DSP_A_HOST:?err}
env_file:
- .env
volumes:
- - ./services/dsp-a:/workspace
+ - ./services/ad-tech:/workspace
- dsp_a_node_modules:/workspace/node_modules
networks:
- adnetwork
dsp-b:
- image: gcr.io/privacy-sandbox-demos/dsp-b:latest
- build: ./services/dsp-b
+ image: gcr.io/privacy-sandbox-demos/ad-tech:latest
+ build: ./services/ad-tech
container_name: "sandcastle_dsp_b"
hostname: ${DSP_B_HOST:?err}
env_file:
- .env
volumes:
- - ./services/dsp-b:/workspace
+ - ./services/ad-tech:/workspace
- dsp_b_node_modules:/workspace/node_modules
networks:
- adnetwork
ssp:
- image: gcr.io/privacy-sandbox-demos/ssp:latest
- build: ./services/ssp
+ image: gcr.io/privacy-sandbox-demos/ad-tech:latest
+ build: ./services/ad-tech
container_name: "sandcastle_ssp"
hostname: ${SSP_HOST:?err}
env_file:
- .env
volumes:
- - ./services/ssp:/workspace
+ - ./services/ad-tech:/workspace
- ssp_node_modules:/workspace/node_modules
networks:
- adnetwork
ssp-a:
- image: gcr.io/privacy-sandbox-demos/ssp-a:latest
- build: ./services/ssp-a
+ image: gcr.io/privacy-sandbox-demos/ad-tech:latest
+ build: ./services/ad-tech
container_name: "sandcastle_ssp_a"
hostname: ${SSP_A_HOST:?err}
env_file:
- .env
volumes:
- - ./services/ssp-a:/workspace
+ - ./services/ad-tech:/workspace
- ssp_a_node_modules:/workspace/node_modules
networks:
- adnetwork
ssp-b:
- image: gcr.io/privacy-sandbox-demos/ssp-b:latest
- build: ./services/ssp-b
+ image: gcr.io/privacy-sandbox-demos/ad-tech:latest
+ build: ./services/ad-tech
container_name: "sandcastle_ssp_b"
hostname: ${SSP_B_HOST:?err}
env_file:
- .env
volumes:
- - ./services/ssp-b:/workspace
+ - ./services/ad-tech:/workspace
- ssp_b_node_modules:/workspace/node_modules
networks:
- adnetwork
ad-server:
- image: gcr.io/privacy-sandbox-demos/ad-server:latest
- build: ./services/ad-server
+ image: gcr.io/privacy-sandbox-demos/ad-tech:latest
+ build: ./services/ad-tech
container_name: "sandcastle_ad_server"
hostname: ${AD_SERVER_HOST:?err}
env_file:
- .env
volumes:
- - ./services/ad-server:/workspace
+ - ./services/ad-tech:/workspace
- ad_server_node_modules:/workspace/node_modules
networks:
- adnetwork
@@ -169,31 +164,6 @@ services:
networks:
- adnetwork
- topics:
- image: gcr.io/privacy-sandbox-demos/topics:latest
- build: ./services/topics
- container_name: "sandcastle_topics"
- env_file:
- - .env
- volumes:
- - ./services/topics:/workspace
- - topics_node_modules:/workspace/node_modules
- networks:
- - adnetwork
-
- topics-server:
- image: gcr.io/privacy-sandbox-demos/topics-server:latest
- build: ./services/topics-server
- container_name: "sandcastle_topics-server"
- hostname: ${TOPICS_SERVER_HOST:?err}
- env_file:
- - .env
- volumes:
- - ./services/topics-server:/workspace
- - topics-server_node_modules:/workspace/node_modules
- networks:
- - adnetwork
-
nginx:
image: nginx:1.22.1-alpine
container_name: "proxy"
@@ -224,10 +194,7 @@ services:
- dsp-b
- ad-server
- collector
- - topics
- - topics-server
networks:
adnetwork:
- name: sandcastle-network
driver: bridge
diff --git a/docs/dependencies.md b/docs/dependencies.md
new file mode 100644
index 00000000..0b055723
--- /dev/null
+++ b/docs/dependencies.md
@@ -0,0 +1,37 @@
+# Codebase Dependencies
+
+You may find it useful make changes to the codebase beyond the files that integrate directly with Privacy Sandbox APIs. You are welcome to do so! For
+your convenience here are some notes about other technologies used in this codebase.
+
+## What’s in this framework ?
+
+This framework does use but does not provide guidance about the following web technologies. Knowledge of the following will enable a more focused
+exploration of Privacy Sandbox APIs.
+
+
+ Express (Node.js web application framework)
+
+ This lightweight server side technology is used to organize and serve
+ each of the sites in the demos such as the shop or news site
+
+ EJS (Embedded Javascript templating)
+
+ This view templating engine enable enables easier maintenance of some of
+ the repetitive content in the demo, such as the product pages in the shop
+ site.
+
+ Typescript
+
+ Typescript is used in the implementation of each demo site's web
+ application alongside Express. However, most direct integration with
+ Privacy Sandbox APIs is done in JavaScript.
+
+ CSS
+
+ CSS is used extensively throughout the demo to enable a more streamlined
+ user experience when testing the Privacy Sandbox integrations.
+
+
+
+Additionally, this codebase does not provide extensive information about Advertising Technology. You should be familiar with these before you start
+exploring. We recommend the following resource to learn more:
diff --git a/firebase.json b/firebase.json
index 9abae495..df913aaa 100644
--- a/firebase.json
+++ b/firebase.json
@@ -2,7 +2,7 @@
"hosting": [
{
"target": "dsp",
- "public": "services/dsp/src/public",
+ "public": "services/ad-tech/src/public",
"ignore": [
"firebase.json",
"**/.*",
@@ -21,7 +21,7 @@
},
{
"target": "dsp-a",
- "public": "services/dsp-a/src/public",
+ "public": "services/ad-tech/src/public",
"ignore": [
"firebase.json",
"**/.*",
@@ -40,7 +40,7 @@
},
{
"target": "dsp-b",
- "public": "services/dsp-b/src/public",
+ "public": "services/ad-tech/src/public",
"ignore": [
"firebase.json",
"**/.*",
@@ -59,7 +59,7 @@
},
{
"target": "shop",
- "public": "services/shop/public",
+ "public": "services/shop/src/public",
"ignore": [
"firebase.json",
"**/.*",
@@ -97,7 +97,7 @@
},
{
"target": "ssp",
- "public": "services/ssp/src/public",
+ "public": "services/ad-tech/src/public",
"ignore": [
"firebase.json",
"**/.*",
@@ -116,7 +116,7 @@
},
{
"target": "ssp-a",
- "public": "services/ssp-a/src/public",
+ "public": "services/ad-tech/src/public",
"ignore": [
"firebase.json",
"**/.*",
@@ -135,7 +135,7 @@
},
{
"target": "ssp-b",
- "public": "services/ssp-b/src/public",
+ "public": "services/ad-tech/src/public",
"ignore": [
"firebase.json",
"**/.*",
@@ -207,24 +207,6 @@
}
]
},
- {
- "target": "topics",
- "ignore": [
- "firebase.json",
- "**/.*",
- "**/**",
- "**/node_modules/**"
- ],
- "rewrites": [
- {
- "source": "**",
- "run": {
- "serviceId": "topics",
- "region": "us-central1"
- }
- }
- ]
- },
{
"target": "topics-motorcycles",
"ignore": [
@@ -237,7 +219,7 @@
{
"source": "**",
"run": {
- "serviceId": "topics",
+ "serviceId": "news",
"region": "us-central1"
}
}
@@ -255,7 +237,7 @@
{
"source": "**",
"run": {
- "serviceId": "topics",
+ "serviceId": "news",
"region": "us-central1"
}
}
@@ -273,25 +255,7 @@
{
"source": "**",
"run": {
- "serviceId": "topics",
- "region": "us-central1"
- }
- }
- ]
- },
- {
- "target": "topics-server",
- "ignore": [
- "firebase.json",
- "**/.*",
- "**/**",
- "**/node_modules/**"
- ],
- "rewrites": [
- {
- "source": "**",
- "run": {
- "serviceId": "topics-server",
+ "serviceId": "news",
"region": "us-central1"
}
}
@@ -299,7 +263,7 @@
},
{
"target": "ad-server",
- "public": "services/ad-server/src/public",
+ "public": "services/ad-tech/src/public",
"ignore": [
"firebase.json",
"**/.*",
diff --git a/monitoring/puppeteer-nodejs/.gcloudignore b/monitoring/puppeteer-nodejs/.gcloudignore
new file mode 100644
index 00000000..00ddecb7
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/.gcloudignore
@@ -0,0 +1,16 @@
+# This file specifies files that are *not* uploaded to Google Cloud
+# using gcloud. It follows the same syntax as .gitignore, with the addition of
+# "#!include" directives (which insert the entries of the given .gitignore-style
+# file at that point).
+#
+# For more information, run:
+# $ gcloud topic gcloudignore
+#
+.gcloudignore
+# If you would like to upload your .git directory, .gitignore file or files
+# from your .gitignore file, remove the corresponding line
+# below:
+.git
+.gitignore
+
+#!include:.gitignore
diff --git a/monitoring/puppeteer-nodejs/.gitignore b/monitoring/puppeteer-nodejs/.gitignore
new file mode 100644
index 00000000..8d2d4c97
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/.gitignore
@@ -0,0 +1,3 @@
+# ignore
+.cache
+node_modules
diff --git a/monitoring/puppeteer-nodejs/.puppeteerrc.cjs b/monitoring/puppeteer-nodejs/.puppeteerrc.cjs
new file mode 100644
index 00000000..536ac071
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/.puppeteerrc.cjs
@@ -0,0 +1,24 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START monitoring_synthetic_monitoring_custom_puppeteer_cjs]
+const {join} = require('path');
+
+/**
+ * @type {import("puppeteer").Configuration}
+ */
+module.exports = {
+ cacheDirectory: join(__dirname, '.cache', 'puppeteer'),
+};
+// [END monitoring_synthetic_monitoring_custom_puppeteer_cjs]
diff --git a/monitoring/puppeteer-nodejs/README.md b/monitoring/puppeteer-nodejs/README.md
new file mode 100644
index 00000000..b79a4ab8
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/README.md
@@ -0,0 +1,55 @@
+# Overview
+
+This package uses the `@google-cloud/synthetics-sdk-api` to create Google Cloud Functions used with Google Cloud Synthetic Monitoring.
+
+## Installation
+
+```shell
+# from root of repo, build all packages
+npm install
+```
+
+## Add a new use case monitoring function
+
+1. Copy the Function Entry Point template in index.js, update the Entry Point name as well as the monitoring function name.
+2. Copy the monitor-uc-template.js, rename the monitoring function and build the monitoring logic.
+
+## Running
+
+The following command runs the selected function (ENTRY_POINT)locally. You will also need to export the environment variable required by your
+function. `export KEY=VALUE` command.
+
+```shell
+npx functions-framework --target=
+```
+
+then run the command below to trigger the function
+
+```shell
+curl http://localhost:8080/
+```
+
+## Deploy to Google Cloud Platform
+
+Setup prerequisites
+
+```shell
+cd
+./script/monitoring_setup.sh
+```
+
+The following command deploys the monitoring/puppeteer-nodejs package to GCP as a cloud function v2.
+
+```shell
+cd
+./script/monitoring_deploy.sh
+```
+
+The following commands deploy the uptime checks and configure the synthetic monitors.
+
+```shell
+cd
+./script/monitoring_uptime.sh
+```
+
+Finally if you want to receive alerts on uptime checks failures, you can configure an alerting policy in Google Cloud console.
diff --git a/monitoring/puppeteer-nodejs/index.js b/monitoring/puppeteer-nodejs/index.js
new file mode 100644
index 00000000..977db4a4
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/index.js
@@ -0,0 +1,81 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// [START monitoring_synthetic_monitoring_custom_puppeteer_script]
+import {
+ instantiateAutoInstrumentation,
+ runSyntheticHandler,
+} from '@google-cloud/synthetics-sdk-api';
+
+// Run instantiateAutoInstrumentation before any other code runs, to get automatic logs and traces
+instantiateAutoInstrumentation();
+import * as functions from '@google-cloud/functions-framework';
+import * as axios from 'axios';
+import * as assert from 'node:assert';
+import * as puppeteer from 'puppeteer';
+
+import {runMonitorUcSingleTouchConversion} from './monitor-uc-single-touch-conversion.js';
+import {runMonitorUcRemarketing} from './monitor-uc-remarketing.js';
+import {runMonitorUcVastVideoPaapi} from './monitor-uc-vast-video-paapi.js';
+import {runMonitorUcVideoMultiSellerSeqAuctionPaapi} from './monitor-uc-video-multi-seller-seq-auction-paapi.js';
+
+// >>> MONITOR TEMPLATE >>>
+// Use Case :
+// functions.http('MonitorUcShortName', runSyntheticHandler(async ({ logger, executionId }) => { // TODO : replace function name with Use Case Short name
+
+// // call implementation in monitor-uc-template.js // TODO : replace with filename
+// await runMonitorUcShortName(logger, executionId); // TODO : replace function name with Use Case Short name
+
+// }));
+// <<< MONITOR TEMPLATE
+
+// Cloud Run Functions Entry points for Synthetic Monitoring with Puppeteer
+
+// Use Case : Single-touch conversion Attribution
+functions.http(
+ 'MonitorUcSingleTouchConversion',
+ runSyntheticHandler(async ({logger, executionId}) => {
+ // call implementation in monitor-uc-single-touch-conversion.js
+ await runMonitorUcSingleTouchConversion(logger, executionId); // Call the exported function
+ }),
+);
+
+// Use Case : Retargeting / Remarketing
+functions.http(
+ 'MonitorUcRemarketing',
+ runSyntheticHandler(async ({logger, executionId}) => {
+ // call implementation in monitor-uc-remarketing.js
+ await runMonitorUcRemarketing(logger, executionId); // Call the exported function
+ }),
+);
+
+// Use Case : Instream VAST video ad in a Protected Audience single-seller auction
+functions.http(
+ 'MonitorUcVastVideoPaapi',
+ runSyntheticHandler(async ({logger, executionId}) => {
+ // call implementation in monitor-uc-vast-video-paapi.js
+ await runMonitorUcVastVideoPaapi(logger, executionId); // Call the exported function
+ }),
+);
+
+// Use Case : Monitor Use Case : Instream video ad in a Protected Audience multi-seller sequential auction setup
+functions.http(
+ 'MonitorUcVideoMultiSellerSeqAuctionPaapi',
+ runSyntheticHandler(async ({logger, executionId}) => {
+ // call implementation in monitor-uc-video-multi-seller-seq-auction-paapi.js
+ await runMonitorUcVideoMultiSellerSeqAuctionPaapi(logger, executionId); // Call the exported function
+ }),
+);
+
+// [END monitoring_synthetic_monitoring_custom_puppeteer_script]
diff --git a/monitoring/puppeteer-nodejs/lib/constants.js b/monitoring/puppeteer-nodejs/lib/constants.js
new file mode 100644
index 00000000..6e5a68ba
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/lib/constants.js
@@ -0,0 +1,59 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// ****************************************************************************
+// ENVIRONMENT VARIABLES
+// ****************************************************************************
+export const {
+ // Home
+ HOME_HOST,
+ HOME_URI,
+
+ // Advertisers
+ SHOP_HOST,
+ SHOP_URI,
+ TRAVEL_HOST,
+ TRAVEL_URI,
+
+ // Publishers
+ NEWS_HOST,
+ NEWS_URI,
+ MOTO_NEWS_HOST,
+ MOTO_NEWS_URI,
+ SOCCER_NEWS_HOST,
+ SOCCER_NEWS_URI,
+ GARDENING_NEWS_HOST,
+ GARDENING_NEWS_URI,
+
+ // Ad-techs
+ DSP_HOST,
+ DSP_URI,
+
+ DSP_A_HOST,
+ DSP_A_URI,
+
+ DSP_B_HOST,
+ DSP_B_URI,
+
+ SSP_HOST,
+ SSP_URI,
+
+ SSP_A_HOST,
+ SSP_A_URI,
+
+ SSP_B_HOST,
+ SSP_B_URI,
+
+ AD_SERVER_HOST,
+ AD_SERVER_URI,
+} = process.env;
diff --git a/monitoring/puppeteer-nodejs/monitor-uc-remarketing.js b/monitoring/puppeteer-nodejs/monitor-uc-remarketing.js
new file mode 100644
index 00000000..b706c893
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/monitor-uc-remarketing.js
@@ -0,0 +1,59 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as axios from 'axios';
+import * as assert from 'node:assert';
+import * as puppeteer from 'puppeteer';
+
+import {SHOP_URI, NEWS_URI} from './lib/constants.js';
+
+// Synthetic Monitoring with Puppeteer
+// Use Case : Retargeting / Remarketing
+async function runMonitorUcRemarketing(logger, executionId) {
+ /*
+ * This function executes the synthetic code for testing purposes.
+ * If the code runs without errors, the synthetic test is considered successful.
+ * If an error is thrown during execution, the synthetic test is considered failed.
+ */
+
+ // Print the use case demo name
+ const usecase = 'Retargeting / Remarketing';
+ logger.info(
+ `Synthetic Monitoring Starts for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Launch a headless Chrome browser and open a new page
+ const browser = await puppeteer.launch({headless: 'new', timeout: 0});
+ const page = await browser.newPage();
+
+ // Navigate to the target URL
+ const result = await page.goto(NEWS_URI, {waitUntil: 'load'});
+
+ // Confirm successful navigation
+ await assert.equal(result.status(), 200);
+
+ // Print the page title to the console
+ const title = await page.title();
+ logger.info(`My Page title: ${title} ` + executionId);
+
+ // Print the use case demo name
+ logger.info(
+ `Synthetic Monitoring Ends for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Close the browser
+ await browser.close();
+}
+
+export {runMonitorUcRemarketing}; // Export the function to make it accessible
diff --git a/monitoring/puppeteer-nodejs/monitor-uc-single-touch-conversion.js b/monitoring/puppeteer-nodejs/monitor-uc-single-touch-conversion.js
new file mode 100644
index 00000000..6acd1a9d
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/monitor-uc-single-touch-conversion.js
@@ -0,0 +1,59 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as axios from 'axios';
+import * as assert from 'node:assert';
+import * as puppeteer from 'puppeteer';
+
+import {SHOP_URI, NEWS_URI} from './lib/constants.js';
+
+// Synthetic Monitoring with Puppeteer
+// Use Case : Single-touch conversion Attribution
+async function runMonitorUcSingleTouchConversion(logger, executionId) {
+ /*
+ * This function executes the synthetic code for testing purposes.
+ * If the code runs without errors, the synthetic test is considered successful.
+ * If an error is thrown during execution, the synthetic test is considered failed.
+ */
+
+ // Print the use case demo name
+ const usecase = 'Single-touch conversion Attribution';
+ logger.info(
+ `Synthetic Monitoring Starts for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Launch a headless Chrome browser and open a new page
+ const browser = await puppeteer.launch({headless: 'new', timeout: 0});
+ const page = await browser.newPage();
+
+ // Navigate to the target URL
+ const result = await page.goto(NEWS_URI, {waitUntil: 'load'});
+
+ // Confirm successful navigation
+ await assert.equal(result.status(), 200);
+
+ // Print the page title to the console
+ const title = await page.title();
+ logger.info(`My Page title: ${title} ` + executionId);
+
+ // Print the use case demo name
+ logger.info(
+ `Synthetic Monitoring Ends for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Close the browser
+ await browser.close();
+}
+
+export {runMonitorUcSingleTouchConversion};
diff --git a/monitoring/puppeteer-nodejs/monitor-uc-template.js b/monitoring/puppeteer-nodejs/monitor-uc-template.js
new file mode 100644
index 00000000..43e529d3
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/monitor-uc-template.js
@@ -0,0 +1,60 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as axios from 'axios';
+import * as assert from 'node:assert';
+import * as puppeteer from 'puppeteer';
+
+import {SHOP_URI, NEWS_URI} from './lib/constants.js';
+
+// Synthetic Monitoring with Puppeteer
+// Use Case :
+async function runMonitorUcShortName(logger, executionId) {
+ // TODO : replace function name with Use Case Short name
+ /*
+ * This function executes the synthetic code for testing purposes.
+ * If the code runs without errors, the synthetic test is considered successful.
+ * If an error is thrown during execution, the synthetic test is considered failed.
+ */
+
+ // Print the use case demo name
+ const usecase = ''; // TODO : replace with use case description
+ logger.info(
+ `Synthetic Monitoring Starts for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Launch a headless Chrome browser and open a new page
+ const browser = await puppeteer.launch({headless: 'new', timeout: 0});
+ const page = await browser.newPage();
+
+ // Navigate to the target URL
+ const result = await page.goto(NEWS_URI, {waitUntil: 'load'});
+
+ // Confirm successful navigation
+ await assert.equal(result.status(), 200);
+
+ // Print the page title to the console
+ const title = await page.title();
+ logger.info(`My Page title: ${title} ` + executionId);
+
+ // Print the use case demo name
+ logger.info(
+ `Synthetic Monitoring Ends for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Close the browser
+ await browser.close();
+}
+
+export {runMonitorUcShortName}; // TODO : replace function name with Use Case Short name
diff --git a/monitoring/puppeteer-nodejs/monitor-uc-vast-video-paapi.js b/monitoring/puppeteer-nodejs/monitor-uc-vast-video-paapi.js
new file mode 100644
index 00000000..bd9184b2
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/monitor-uc-vast-video-paapi.js
@@ -0,0 +1,60 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as axios from 'axios';
+import * as assert from 'node:assert';
+import * as puppeteer from 'puppeteer';
+
+import {SHOP_URI, NEWS_URI} from './lib/constants.js';
+
+// Synthetic Monitoring with Puppeteer
+// Use Case : Instream VAST video ad in a Protected Audience single-seller auction
+async function runMonitorUcVastVideoPaapi(logger, executionId) {
+ /*
+ * This function executes the synthetic code for testing purposes.
+ * If the code runs without errors, the synthetic test is considered successful.
+ * If an error is thrown during execution, the synthetic test is considered failed.
+ */
+
+ // Print the use case demo name
+ const usecase =
+ 'Instream VAST video ad in a Protected Audience single-seller auction';
+ logger.info(
+ `Synthetic Monitoring Starts for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Launch a headless Chrome browser and open a new page
+ const browser = await puppeteer.launch({headless: 'new', timeout: 0});
+ const page = await browser.newPage();
+
+ // Navigate to the target URL
+ const result = await page.goto(NEWS_URI, {waitUntil: 'load'});
+
+ // Confirm successful navigation
+ await assert.equal(result.status(), 200);
+
+ // Print the page title to the console
+ const title = await page.title();
+ logger.info(`My Page title: ${title} ` + executionId);
+
+ // Print the use case demo name
+ logger.info(
+ `Synthetic Monitoring Ends for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Close the browser
+ await browser.close();
+}
+
+export {runMonitorUcVastVideoPaapi}; // Export the function to make it accessible
diff --git a/monitoring/puppeteer-nodejs/monitor-uc-video-multi-seller-seq-auction-paapi.js b/monitoring/puppeteer-nodejs/monitor-uc-video-multi-seller-seq-auction-paapi.js
new file mode 100644
index 00000000..284bf1ad
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/monitor-uc-video-multi-seller-seq-auction-paapi.js
@@ -0,0 +1,63 @@
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as axios from 'axios';
+import * as assert from 'node:assert';
+import * as puppeteer from 'puppeteer';
+
+import {SHOP_URI, NEWS_URI} from './lib/constants.js';
+
+// Synthetic Monitoring with Puppeteer
+// Use Case : Instream video ad in a Protected Audience multi-seller sequential auction setup
+async function runMonitorUcVideoMultiSellerSeqAuctionPaapi(
+ logger,
+ executionId,
+) {
+ /*
+ * This function executes the synthetic code for testing purposes.
+ * If the code runs without errors, the synthetic test is considered successful.
+ * If an error is thrown during execution, the synthetic test is considered failed.
+ */
+
+ // Print the use case demo name
+ const usecase =
+ 'Instream video ad in a Protected Audience multi-seller sequential auction setup';
+ logger.info(
+ `Synthetic Monitoring Starts for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Launch a headless Chrome browser and open a new page
+ const browser = await puppeteer.launch({headless: 'new', timeout: 0});
+ const page = await browser.newPage();
+
+ // Navigate to the target URL
+ const result = await page.goto(NEWS_URI, {waitUntil: 'load'});
+
+ // Confirm successful navigation
+ await assert.equal(result.status(), 200);
+
+ // Print the page title to the console
+ const title = await page.title();
+ logger.info(`My Page title: ${title} ` + executionId);
+
+ // Print the use case demo name
+ logger.info(
+ `Synthetic Monitoring Ends for Privacy Sandbox Demos Use Case : ${usecase} `,
+ );
+
+ // Close the browser
+ await browser.close();
+}
+
+export {runMonitorUcVideoMultiSellerSeqAuctionPaapi}; // Export the function to make it accessible
diff --git a/monitoring/puppeteer-nodejs/package-lock.json b/monitoring/puppeteer-nodejs/package-lock.json
new file mode 100644
index 00000000..1e56ebf8
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/package-lock.json
@@ -0,0 +1,6581 @@
+{
+ "name": "generic-puppeteer-nodejs",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "generic-puppeteer-nodejs",
+ "version": "1.0.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@google-cloud/functions-framework": "^3.4.2",
+ "@google-cloud/synthetics-sdk-api": "^0.6.0",
+ "axios": "^1.7.7",
+ "puppeteer": "^23.7.1"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.25.9",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/highlight": "^7.25.9",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.25.9",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.25.9",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.5.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/@dabh/diagnostics": {
+ "version": "2.0.3",
+ "license": "MIT",
+ "dependencies": {
+ "colorspace": "1.1.x",
+ "enabled": "2.0.x",
+ "kuler": "^2.0.0"
+ }
+ },
+ "node_modules/@google-cloud/functions-framework": {
+ "version": "3.4.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/express": "4.17.21",
+ "body-parser": "^1.18.3",
+ "cloudevents": "^8.0.0",
+ "express": "^4.16.4",
+ "minimist": "^1.2.7",
+ "on-finished": "^2.3.0",
+ "read-pkg-up": "^7.0.1",
+ "semver": "^7.3.5"
+ },
+ "bin": {
+ "functions-framework": "build/src/main.js",
+ "functions-framework-nodejs": "build/src/main.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter": {
+ "version": "2.1.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@google-cloud/opentelemetry-resource-util": "^2.1.0",
+ "@grpc/grpc-js": "^1.1.8",
+ "@grpc/proto-loader": "^0.7.0",
+ "google-auth-library": "^7.0.0",
+ "google-proto-files": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0",
+ "@opentelemetry/core": "^1.0.0",
+ "@opentelemetry/resources": "^1.0.0",
+ "@opentelemetry/sdk-trace-base": "^1.0.0"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter/node_modules/agent-base": {
+ "version": "6.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter/node_modules/debug": {
+ "version": "4.3.7",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter/node_modules/gaxios": {
+ "version": "4.3.3",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^5.0.0",
+ "is-stream": "^2.0.0",
+ "node-fetch": "^2.6.7"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter/node_modules/gcp-metadata": {
+ "version": "4.3.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^4.0.0",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter/node_modules/google-auth-library": {
+ "version": "7.14.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "arrify": "^2.0.0",
+ "base64-js": "^1.3.0",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "fast-text-encoding": "^1.0.0",
+ "gaxios": "^4.0.0",
+ "gcp-metadata": "^4.2.0",
+ "gtoken": "^5.0.4",
+ "jws": "^4.0.0",
+ "lru-cache": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter/node_modules/gtoken": {
+ "version": "5.3.2",
+ "license": "MIT",
+ "dependencies": {
+ "gaxios": "^4.0.0",
+ "google-p12-pem": "^3.1.3",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter/node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@google-cloud/opentelemetry-cloud-trace-exporter/node_modules/ms": {
+ "version": "2.1.3",
+ "license": "MIT"
+ },
+ "node_modules/@google-cloud/opentelemetry-resource-util": {
+ "version": "2.4.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "^1.22.0",
+ "gcp-metadata": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/resources": "^1.0.0"
+ }
+ },
+ "node_modules/@google-cloud/synthetics-sdk-api": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@google-cloud/synthetics-sdk-api/-/synthetics-sdk-api-0.6.0.tgz",
+ "integrity": "sha512-dRS3x7NAYUdET6SQ6+scu3eUGUtgH2PAY8Zx+0DDvB7Zo5ymVIP1b0hbAkLLDZzg9wNQFSDAh59A0lEuU3Zpyw==",
+ "dependencies": {
+ "@google-cloud/opentelemetry-cloud-trace-exporter": "2.1.0",
+ "@opentelemetry/api": "1.6.0",
+ "@opentelemetry/auto-instrumentations-node": "0.39.2",
+ "@opentelemetry/instrumentation": "0.43.0",
+ "@opentelemetry/sdk-node": "0.43.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0",
+ "@opentelemetry/sdk-trace-node": "1.17.0",
+ "axios": "1.6.7",
+ "error-stack-parser": "2.1.4",
+ "google-auth-library": "9.0.0",
+ "ts-proto": "1.148.1",
+ "winston": "3.10.0"
+ }
+ },
+ "node_modules/@google-cloud/synthetics-sdk-api/node_modules/@opentelemetry/api": {
+ "version": "1.6.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@google-cloud/synthetics-sdk-api/node_modules/axios": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz",
+ "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==",
+ "dependencies": {
+ "follow-redirects": "^1.15.4",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.12.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.7.13",
+ "@js-sdsl/ordered-map": "^4.4.2"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.13",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@hapi/b64": {
+ "version": "5.0.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "9.x.x"
+ }
+ },
+ "node_modules/@hapi/boom": {
+ "version": "9.1.4",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "9.x.x"
+ }
+ },
+ "node_modules/@hapi/bourne": {
+ "version": "2.1.0",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@hapi/cryptiles": {
+ "version": "5.1.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/boom": "9.x.x"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@hapi/hoek": {
+ "version": "9.3.0",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@hapi/iron": {
+ "version": "6.0.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/b64": "5.x.x",
+ "@hapi/boom": "9.x.x",
+ "@hapi/bourne": "2.x.x",
+ "@hapi/cryptiles": "5.x.x",
+ "@hapi/hoek": "9.x.x"
+ }
+ },
+ "node_modules/@hapi/podium": {
+ "version": "4.1.3",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "9.x.x",
+ "@hapi/teamwork": "5.x.x",
+ "@hapi/validate": "1.x.x"
+ }
+ },
+ "node_modules/@hapi/teamwork": {
+ "version": "5.1.1",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@hapi/topo": {
+ "version": "5.1.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0"
+ }
+ },
+ "node_modules/@hapi/validate": {
+ "version": "1.1.3",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0",
+ "@hapi/topo": "^5.0.0"
+ }
+ },
+ "node_modules/@js-sdsl/ordered-map": {
+ "version": "4.4.2",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/js-sdsl"
+ }
+ },
+ "node_modules/@opentelemetry/api": {
+ "version": "1.4.1",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/api-logs": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node": {
+ "version": "0.39.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.41.2",
+ "@opentelemetry/instrumentation-amqplib": "^0.33.1",
+ "@opentelemetry/instrumentation-aws-lambda": "^0.37.0",
+ "@opentelemetry/instrumentation-aws-sdk": "^0.36.0",
+ "@opentelemetry/instrumentation-bunyan": "^0.32.1",
+ "@opentelemetry/instrumentation-cassandra-driver": "^0.33.1",
+ "@opentelemetry/instrumentation-connect": "^0.32.1",
+ "@opentelemetry/instrumentation-cucumber": "^0.1.0",
+ "@opentelemetry/instrumentation-dataloader": "^0.5.1",
+ "@opentelemetry/instrumentation-dns": "^0.32.2",
+ "@opentelemetry/instrumentation-express": "^0.33.1",
+ "@opentelemetry/instrumentation-fastify": "^0.32.2",
+ "@opentelemetry/instrumentation-fs": "^0.8.1",
+ "@opentelemetry/instrumentation-generic-pool": "^0.32.2",
+ "@opentelemetry/instrumentation-graphql": "^0.35.1",
+ "@opentelemetry/instrumentation-grpc": "^0.41.2",
+ "@opentelemetry/instrumentation-hapi": "^0.33.0",
+ "@opentelemetry/instrumentation-http": "^0.41.2",
+ "@opentelemetry/instrumentation-ioredis": "^0.35.1",
+ "@opentelemetry/instrumentation-knex": "^0.32.1",
+ "@opentelemetry/instrumentation-koa": "^0.36.0",
+ "@opentelemetry/instrumentation-lru-memoizer": "^0.33.1",
+ "@opentelemetry/instrumentation-memcached": "^0.32.1",
+ "@opentelemetry/instrumentation-mongodb": "^0.37.0",
+ "@opentelemetry/instrumentation-mongoose": "^0.33.1",
+ "@opentelemetry/instrumentation-mysql": "^0.34.1",
+ "@opentelemetry/instrumentation-mysql2": "^0.34.1",
+ "@opentelemetry/instrumentation-nestjs-core": "^0.33.1",
+ "@opentelemetry/instrumentation-net": "^0.32.1",
+ "@opentelemetry/instrumentation-pg": "^0.36.1",
+ "@opentelemetry/instrumentation-pino": "^0.34.1",
+ "@opentelemetry/instrumentation-redis": "^0.35.1",
+ "@opentelemetry/instrumentation-redis-4": "^0.35.1",
+ "@opentelemetry/instrumentation-restify": "^0.34.0",
+ "@opentelemetry/instrumentation-router": "^0.33.1",
+ "@opentelemetry/instrumentation-socket.io": "^0.34.1",
+ "@opentelemetry/instrumentation-tedious": "^0.6.1",
+ "@opentelemetry/instrumentation-winston": "^0.32.1",
+ "@opentelemetry/resource-detector-alibaba-cloud": "^0.28.1",
+ "@opentelemetry/resource-detector-aws": "^1.3.1",
+ "@opentelemetry/resource-detector-container": "^0.3.1",
+ "@opentelemetry/resource-detector-gcp": "^0.29.1",
+ "@opentelemetry/resources": "^1.12.0",
+ "@opentelemetry/sdk-node": "^0.41.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.4.1"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/api-logs": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/context-async-hooks": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/core": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-jaeger": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/sdk-trace-base": "1.15.2",
+ "@opentelemetry/semantic-conventions": "1.15.2",
+ "jaeger-client": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-trace-otlp-grpc": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/otlp-grpc-exporter-base": "0.41.2",
+ "@opentelemetry/otlp-transformer": "0.41.2",
+ "@opentelemetry/resources": "1.15.2",
+ "@opentelemetry/sdk-trace-base": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-trace-otlp-http": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/otlp-exporter-base": "0.41.2",
+ "@opentelemetry/otlp-transformer": "0.41.2",
+ "@opentelemetry/resources": "1.15.2",
+ "@opentelemetry/sdk-trace-base": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-trace-otlp-proto": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/otlp-exporter-base": "0.41.2",
+ "@opentelemetry/otlp-proto-exporter-base": "0.41.2",
+ "@opentelemetry/otlp-transformer": "0.41.2",
+ "@opentelemetry/resources": "1.15.2",
+ "@opentelemetry/sdk-trace-base": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/exporter-zipkin": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/resources": "1.15.2",
+ "@opentelemetry/sdk-trace-base": "1.15.2",
+ "@opentelemetry/semantic-conventions": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.1",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/otlp-grpc-exporter-base": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/otlp-exporter-base": "0.41.2",
+ "protobufjs": "^7.2.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/otlp-proto-exporter-base": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/otlp-exporter-base": "0.41.2",
+ "protobufjs": "^7.2.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.41.2",
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/resources": "1.15.2",
+ "@opentelemetry/sdk-logs": "0.41.2",
+ "@opentelemetry/sdk-metrics": "1.15.2",
+ "@opentelemetry/sdk-trace-base": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/propagator-b3": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/propagator-jaeger": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/resources": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/semantic-conventions": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/resources": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.5.0",
+ "@opentelemetry/api-logs": ">=0.39.1"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/resources": "1.15.2",
+ "lodash.merge": "^4.6.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-node": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.41.2",
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/exporter-jaeger": "1.15.2",
+ "@opentelemetry/exporter-trace-otlp-grpc": "0.41.2",
+ "@opentelemetry/exporter-trace-otlp-http": "0.41.2",
+ "@opentelemetry/exporter-trace-otlp-proto": "0.41.2",
+ "@opentelemetry/exporter-zipkin": "1.15.2",
+ "@opentelemetry/instrumentation": "0.41.2",
+ "@opentelemetry/resources": "1.15.2",
+ "@opentelemetry/sdk-logs": "0.41.2",
+ "@opentelemetry/sdk-metrics": "1.15.2",
+ "@opentelemetry/sdk-trace-base": "1.15.2",
+ "@opentelemetry/sdk-trace-node": "1.15.2",
+ "@opentelemetry/semantic-conventions": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/resources": "1.15.2",
+ "@opentelemetry/semantic-conventions": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/sdk-trace-node": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/context-async-hooks": "1.15.2",
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/propagator-b3": "1.15.2",
+ "@opentelemetry/propagator-jaeger": "1.15.2",
+ "@opentelemetry/sdk-trace-base": "1.15.2",
+ "semver": "^7.5.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/auto-instrumentations-node/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/context-async-hooks": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/core": {
+ "version": "1.26.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.27.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-jaeger": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0",
+ "jaeger-client": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-jaeger/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-jaeger/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/otlp-grpc-exporter-base": "0.43.0",
+ "@opentelemetry/otlp-transformer": "0.43.0",
+ "@opentelemetry/resources": "1.17.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/resources": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-grpc/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-http": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/otlp-exporter-base": "0.43.0",
+ "@opentelemetry/otlp-transformer": "0.43.0",
+ "@opentelemetry/resources": "1.17.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/resources": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-http/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/otlp-exporter-base": "0.43.0",
+ "@opentelemetry/otlp-proto-exporter-base": "0.43.0",
+ "@opentelemetry/otlp-transformer": "0.43.0",
+ "@opentelemetry/resources": "1.17.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/resources": "1.17.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/resources": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/exporter-zipkin/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-amqplib": {
+ "version": "0.33.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-amqplib/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-aws-lambda": {
+ "version": "0.37.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/propagator-aws-xray": "^1.3.1",
+ "@opentelemetry/resources": "^1.8.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/aws-lambda": "8.10.122"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-aws-lambda/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-aws-sdk": {
+ "version": "0.36.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.45.1",
+ "@opentelemetry/propagation-utils": "^0.30.3",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-aws-sdk/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.45.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-bunyan": {
+ "version": "0.32.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.44.0",
+ "@types/bunyan": "1.8.9"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-bunyan/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.44.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-cassandra-driver": {
+ "version": "0.33.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.44.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-cassandra-driver/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.44.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-connect": {
+ "version": "0.32.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/connect": "3.4.36"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-connect/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-connect/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-cucumber": {
+ "version": "0.1.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.45.1",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-cucumber/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.45.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-dataloader": {
+ "version": "0.5.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-dataloader/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-dns": {
+ "version": "0.32.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-dns/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-dns/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-express": {
+ "version": "0.33.3",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.45.1",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/express": "4.17.18"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-express/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.45.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-express/node_modules/@types/express": {
+ "version": "4.17.18",
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fastify": {
+ "version": "0.32.6",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fastify/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fastify/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fs": {
+ "version": "0.8.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fs/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-fs/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-generic-pool": {
+ "version": "0.32.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-generic-pool/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-graphql": {
+ "version": "0.35.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.44.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-graphql/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.44.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-grpc": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "0.41.2",
+ "@opentelemetry/semantic-conventions": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.1",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-grpc/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-hapi": {
+ "version": "0.33.3",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/hapi__hapi": "20.0.13"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-hapi/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-hapi/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-http": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.15.2",
+ "@opentelemetry/instrumentation": "0.41.2",
+ "@opentelemetry/semantic-conventions": "1.15.2",
+ "semver": "^7.5.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/core": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.15.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.5.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.41.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.1",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.15.2",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-ioredis": {
+ "version": "0.35.3",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.45.1",
+ "@opentelemetry/redis-common": "^0.36.1",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/ioredis4": "npm:@types/ioredis@^4.28.10"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-ioredis/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.45.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-knex": {
+ "version": "0.32.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-knex/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-knex/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-koa": {
+ "version": "0.36.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/koa": "2.13.9",
+ "@types/koa__router": "12.0.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-koa/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-koa/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-lru-memoizer": {
+ "version": "0.33.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-lru-memoizer/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-memcached": {
+ "version": "0.32.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/memcached": "^2.2.6"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-memcached/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-memcached/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mongodb": {
+ "version": "0.37.3",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.45.1",
+ "@opentelemetry/sdk-metrics": "^1.9.1",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mongodb/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.45.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mongoose": {
+ "version": "0.33.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.45.1",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mongoose/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.45.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql": {
+ "version": "0.34.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/mysql": "2.15.22"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql2": {
+ "version": "0.34.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@opentelemetry/sql-common": "^0.40.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-mysql2/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-nestjs-core": {
+ "version": "0.33.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-nestjs-core/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-nestjs-core/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-net": {
+ "version": "0.32.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-net/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-net/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pg": {
+ "version": "0.36.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.44.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@opentelemetry/sql-common": "^0.40.0",
+ "@types/pg": "8.6.1",
+ "@types/pg-pool": "2.0.4"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pg/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.44.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pino": {
+ "version": "0.34.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pino/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-pino/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-redis": {
+ "version": "0.35.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/redis-common": "^0.36.1",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-redis-4": {
+ "version": "0.35.6",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/redis-common": "^0.36.1",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-redis-4/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-redis/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-redis/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-restify": {
+ "version": "0.34.3",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.8.0",
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-restify/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-restify/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-router": {
+ "version": "0.33.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-router/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-router/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-socket.io": {
+ "version": "0.34.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.45.1",
+ "@opentelemetry/semantic-conventions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14.0"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-socket.io/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.45.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-tedious": {
+ "version": "0.6.5",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.46.0",
+ "@opentelemetry/semantic-conventions": "^1.0.0",
+ "@types/tedious": "^4.0.10"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-tedious/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.46.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.7.1",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-tedious/node_modules/import-in-the-middle": {
+ "version": "1.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-winston": {
+ "version": "0.32.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/instrumentation": "^0.44.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/instrumentation-winston/node_modules/@opentelemetry/instrumentation": {
+ "version": "0.44.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/shimmer": "^1.0.2",
+ "import-in-the-middle": "1.4.2",
+ "require-in-the-middle": "^7.1.1",
+ "semver": "^7.5.2",
+ "shimmer": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.3.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-exporter-base": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-exporter-base/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.7.1",
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/otlp-exporter-base": "0.43.0",
+ "protobufjs": "^7.2.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-grpc-exporter-base/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-proto-exporter-base": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/otlp-exporter-base": "0.43.0",
+ "protobufjs": "^7.2.3"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-proto-exporter-base/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-proto-exporter-base/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.43.0",
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/resources": "1.17.0",
+ "@opentelemetry/sdk-logs": "0.43.0",
+ "@opentelemetry/sdk-metrics": "1.17.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/resources": "1.17.0",
+ "lodash.merge": "^4.6.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/propagation-utils": {
+ "version": "0.30.11",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-aws-xray": {
+ "version": "1.26.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.26.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-b3": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-b3/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-b3/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-jaeger": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/propagator-jaeger/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/redis-common": {
+ "version": "0.36.2",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-alibaba-cloud": {
+ "version": "0.28.10",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/resources": "^1.0.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-aws": {
+ "version": "1.6.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.0.0",
+ "@opentelemetry/resources": "^1.10.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-container": {
+ "version": "0.3.11",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/resources": "^1.0.0",
+ "@opentelemetry/semantic-conventions": "^1.22.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resource-detector-gcp": {
+ "version": "0.29.12",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.0.0",
+ "@opentelemetry/resources": "^1.10.0",
+ "@opentelemetry/semantic-conventions": "^1.27.0",
+ "gcp-metadata": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.0.0"
+ }
+ },
+ "node_modules/@opentelemetry/resources": {
+ "version": "1.26.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.26.0",
+ "@opentelemetry/semantic-conventions": "1.27.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-logs": {
+ "version": "0.43.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/resources": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.4.0 <1.7.0",
+ "@opentelemetry/api-logs": ">=0.39.1"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-metrics": {
+ "version": "1.26.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.26.0",
+ "@opentelemetry/resources": "1.26.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.10.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node": {
+ "version": "0.43.0",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/api-logs": "0.43.0",
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/exporter-jaeger": "1.17.0",
+ "@opentelemetry/exporter-trace-otlp-grpc": "0.43.0",
+ "@opentelemetry/exporter-trace-otlp-http": "0.43.0",
+ "@opentelemetry/exporter-trace-otlp-proto": "0.43.0",
+ "@opentelemetry/exporter-zipkin": "1.17.0",
+ "@opentelemetry/instrumentation": "0.43.0",
+ "@opentelemetry/resources": "1.17.0",
+ "@opentelemetry/sdk-logs": "0.43.0",
+ "@opentelemetry/sdk-metrics": "1.17.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0",
+ "@opentelemetry/sdk-trace-node": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/resources": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/sdk-metrics": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/resources": "1.17.0",
+ "lodash.merge": "^4.6.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.3.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-node/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/resources": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/context-async-hooks": "1.17.0",
+ "@opentelemetry/core": "1.17.0",
+ "@opentelemetry/propagator-b3": "1.17.0",
+ "@opentelemetry/propagator-jaeger": "1.17.0",
+ "@opentelemetry/sdk-trace-base": "1.17.0",
+ "semver": "^7.5.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/core": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/semantic-conventions": "1.17.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": ">=1.0.0 <1.7.0"
+ }
+ },
+ "node_modules/@opentelemetry/sdk-trace-node/node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.17.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/semantic-conventions": {
+ "version": "1.27.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@opentelemetry/sql-common": {
+ "version": "0.40.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@opentelemetry/core": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "@opentelemetry/api": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.4",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.0",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1",
+ "@protobufjs/inquire": "^1.1.0"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/inquire": {
+ "version": "1.1.0",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.0",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@puppeteer/browsers": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.4.1.tgz",
+ "integrity": "sha512-0kdAbmic3J09I6dT8e9vE2JOCSt13wHCW5x/ly8TSt2bDtuIWe2TgLZZDHdcziw9AVCzflMAXCrVyRIhIs44Ng==",
+ "dependencies": {
+ "debug": "^4.3.7",
+ "extract-zip": "^2.0.1",
+ "progress": "^2.0.3",
+ "proxy-agent": "^6.4.0",
+ "semver": "^7.6.3",
+ "tar-fs": "^3.0.6",
+ "unbzip2-stream": "^1.4.3",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "browsers": "lib/cjs/main-cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@puppeteer/browsers/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/@sideway/address": {
+ "version": "4.1.5",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0"
+ }
+ },
+ "node_modules/@sideway/formula": {
+ "version": "3.0.1",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@sideway/pinpoint": {
+ "version": "2.0.0",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@tootallnate/quickjs-emscripten": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
+ "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA=="
+ },
+ "node_modules/@types/accepts": {
+ "version": "1.3.7",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/aws-lambda": {
+ "version": "8.10.122",
+ "license": "MIT"
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.5",
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/bunyan": {
+ "version": "1.8.9",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.36",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/content-disposition": {
+ "version": "0.5.8",
+ "license": "MIT"
+ },
+ "node_modules/@types/cookies": {
+ "version": "0.9.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/express": "*",
+ "@types/keygrip": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.21",
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.19.6",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/hapi__catbox": {
+ "version": "10.2.6",
+ "license": "MIT"
+ },
+ "node_modules/@types/hapi__hapi": {
+ "version": "20.0.13",
+ "license": "MIT",
+ "dependencies": {
+ "@hapi/boom": "^9.0.0",
+ "@hapi/iron": "^6.0.0",
+ "@hapi/podium": "^4.1.3",
+ "@types/hapi__catbox": "*",
+ "@types/hapi__mimos": "*",
+ "@types/hapi__shot": "*",
+ "@types/node": "*",
+ "joi": "^17.3.0"
+ }
+ },
+ "node_modules/@types/hapi__mimos": {
+ "version": "4.1.4",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mime-db": "*"
+ }
+ },
+ "node_modules/@types/hapi__shot": {
+ "version": "4.1.6",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/http-assert": {
+ "version": "1.5.5",
+ "license": "MIT"
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.4",
+ "license": "MIT"
+ },
+ "node_modules/@types/ioredis4": {
+ "name": "@types/ioredis",
+ "version": "4.28.10",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/keygrip": {
+ "version": "1.0.6",
+ "license": "MIT"
+ },
+ "node_modules/@types/koa": {
+ "version": "2.13.9",
+ "license": "MIT",
+ "dependencies": {
+ "@types/accepts": "*",
+ "@types/content-disposition": "*",
+ "@types/cookies": "*",
+ "@types/http-assert": "*",
+ "@types/http-errors": "*",
+ "@types/keygrip": "*",
+ "@types/koa-compose": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/koa__router": {
+ "version": "12.0.3",
+ "license": "MIT",
+ "dependencies": {
+ "@types/koa": "*"
+ }
+ },
+ "node_modules/@types/koa-compose": {
+ "version": "3.2.8",
+ "license": "MIT",
+ "dependencies": {
+ "@types/koa": "*"
+ }
+ },
+ "node_modules/@types/long": {
+ "version": "4.0.2",
+ "license": "MIT"
+ },
+ "node_modules/@types/memcached": {
+ "version": "2.2.10",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.5",
+ "license": "MIT"
+ },
+ "node_modules/@types/mime-db": {
+ "version": "1.43.5",
+ "license": "MIT"
+ },
+ "node_modules/@types/mysql": {
+ "version": "2.15.22",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "22.7.9",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
+ },
+ "node_modules/@types/normalize-package-data": {
+ "version": "2.4.4",
+ "license": "MIT"
+ },
+ "node_modules/@types/object-hash": {
+ "version": "1.3.4",
+ "license": "MIT"
+ },
+ "node_modules/@types/pg": {
+ "version": "8.6.1",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "pg-protocol": "*",
+ "pg-types": "^2.2.0"
+ }
+ },
+ "node_modules/@types/pg-pool": {
+ "version": "2.0.4",
+ "license": "MIT",
+ "dependencies": {
+ "@types/pg": "*"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.16",
+ "license": "MIT"
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "0.17.4",
+ "license": "MIT",
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.7",
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/shimmer": {
+ "version": "1.2.0",
+ "license": "MIT"
+ },
+ "node_modules/@types/tedious": {
+ "version": "4.0.14",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/triple-beam": {
+ "version": "1.3.5",
+ "license": "MIT"
+ },
+ "node_modules/@types/yauzl": {
+ "version": "2.10.3",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
+ "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.13.0",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-import-assertions": {
+ "version": "1.9.0",
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^8"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.1",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/agent-base/node_modules/debug": {
+ "version": "4.3.7",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/agent-base/node_modules/ms": {
+ "version": "2.1.3",
+ "license": "MIT"
+ },
+ "node_modules/ajv": {
+ "version": "8.17.1",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ansi-color": {
+ "version": "0.2.1"
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "license": "Python-2.0"
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "license": "MIT"
+ },
+ "node_modules/arrify": {
+ "version": "2.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ast-types": {
+ "version": "0.13.4",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
+ "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
+ "dependencies": {
+ "tslib": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.6",
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "license": "MIT"
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.7.7",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/b4a": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
+ "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg=="
+ },
+ "node_modules/bare-events": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz",
+ "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==",
+ "optional": true
+ },
+ "node_modules/bare-fs": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.5.tgz",
+ "integrity": "sha512-SlE9eTxifPDJrT6YgemQ1WGFleevzwY+XAP1Xqgl56HtcrisC2CHCZ2tq6dBpcH2TnNxwUEUGhweo+lrQtYuiw==",
+ "optional": true,
+ "dependencies": {
+ "bare-events": "^2.0.0",
+ "bare-path": "^2.0.0",
+ "bare-stream": "^2.0.0"
+ }
+ },
+ "node_modules/bare-os": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.4.tgz",
+ "integrity": "sha512-z3UiI2yi1mK0sXeRdc4O1Kk8aOa/e+FNWZcTiPB/dfTWyLypuE99LibgRaQki914Jq//yAWylcAt+mknKdixRQ==",
+ "optional": true
+ },
+ "node_modules/bare-path": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz",
+ "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==",
+ "optional": true,
+ "dependencies": {
+ "bare-os": "^2.1.0"
+ }
+ },
+ "node_modules/bare-stream": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.3.2.tgz",
+ "integrity": "sha512-EFZHSIBkDgSHIwj2l2QZfP4U5OcD4xFAOwhSb/vlr9PIqyGJGvB/nfClJbcnh3EY4jtPE4zsb5ztae96bVF79A==",
+ "optional": true,
+ "dependencies": {
+ "streamx": "^2.20.0"
+ }
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/basic-ftp": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
+ "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/bignumber.js": {
+ "version": "9.1.2",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.3",
+ "license": "MIT",
+ "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.13.0",
+ "raw-body": "2.5.2",
+ "type-is": "~1.6.18",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/bufrw": {
+ "version": "1.4.0",
+ "dependencies": {
+ "ansi-color": "^0.2.1",
+ "error": "^7.0.0",
+ "hexer": "^1.5.0",
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10.x"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/case-anything": {
+ "version": "2.1.13",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chromium-bidi": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.8.0.tgz",
+ "integrity": "sha512-uJydbGdTw0DEUjhoogGveneJVWX/9YuqkWePzMmkBYwtdAqo5d3J/ovNKFr+/2hWXYmYCr6it8mSSTIj6SS6Ug==",
+ "dependencies": {
+ "mitt": "3.0.1",
+ "urlpattern-polyfill": "10.0.0",
+ "zod": "3.23.8"
+ },
+ "peerDependencies": {
+ "devtools-protocol": "*"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.1",
+ "license": "MIT"
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cloudevents": {
+ "version": "8.0.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "ajv": "^8.11.0",
+ "ajv-formats": "^2.1.1",
+ "json-bigint": "^1.0.0",
+ "process": "^0.11.10",
+ "util": "^0.12.4",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">=16 <=22"
+ }
+ },
+ "node_modules/color": {
+ "version": "3.2.1",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.3",
+ "color-string": "^1.6.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "license": "MIT"
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/colorspace": {
+ "version": "1.1.4",
+ "license": "MIT",
+ "dependencies": {
+ "color": "^3.1.3",
+ "text-hex": "1.0.x"
+ }
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "license": "MIT"
+ },
+ "node_modules/cosmiconfig": {
+ "version": "9.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "env-paths": "^2.2.1",
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
+ "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/dataloader": {
+ "version": "1.4.0",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/debug": {
+ "version": "2.6.9",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/degenerator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
+ "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
+ "dependencies": {
+ "ast-types": "^0.13.4",
+ "escodegen": "^2.1.0",
+ "esprima": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "1.0.3",
+ "license": "Apache-2.0",
+ "bin": {
+ "detect-libc": "bin/detect-libc.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/devtools-protocol": {
+ "version": "0.0.1354347",
+ "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1354347.tgz",
+ "integrity": "sha512-BlmkSqV0V84E2WnEnoPnwyix57rQxAM5SKJjf4TbYOCGLAWtz8CDH8RIaGOjPgPCXo2Mce3kxSY497OySidY3Q=="
+ },
+ "node_modules/dprint-node": {
+ "version": "1.0.8",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^1.0.3"
+ }
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "license": "MIT"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "license": "MIT"
+ },
+ "node_modules/enabled": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/error": {
+ "version": "7.0.2",
+ "dependencies": {
+ "string-template": "~0.2.1",
+ "xtend": "~4.0.0"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "license": "MIT",
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/escodegen": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "dependencies": {
+ "esprima": "^4.0.1",
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
+ },
+ "bin": {
+ "escodegen": "bin/escodegen.js",
+ "esgenerate": "bin/esgenerate.js"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "optionalDependencies": {
+ "source-map": "~0.6.1"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.21.1",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "1.20.3",
+ "content-disposition": "0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "0.7.1",
+ "cookie-signature": "1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "1.3.1",
+ "fresh": "0.5.2",
+ "http-errors": "2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "0.1.10",
+ "proxy-addr": "~2.0.7",
+ "qs": "6.13.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "0.19.0",
+ "serve-static": "1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "license": "MIT"
+ },
+ "node_modules/extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "extract-zip": "cli.js"
+ },
+ "engines": {
+ "node": ">= 10.17.0"
+ },
+ "optionalDependencies": {
+ "@types/yauzl": "^2.9.1"
+ }
+ },
+ "node_modules/extract-zip/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/extract-zip/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "license": "MIT"
+ },
+ "node_modules/fast-fifo": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
+ "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="
+ },
+ "node_modules/fast-text-encoding": {
+ "version": "1.0.6",
+ "license": "Apache-2.0"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.0.3",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/fecha": {
+ "version": "4.2.3",
+ "license": "MIT"
+ },
+ "node_modules/finalhandler": {
+ "version": "1.3.1",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "on-finished": "2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "2.0.1",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "4.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fn.name": {
+ "version": "1.1.0",
+ "license": "MIT"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
+ "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gaxios": {
+ "version": "6.7.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "extend": "^3.0.2",
+ "https-proxy-agent": "^7.0.1",
+ "is-stream": "^2.0.0",
+ "node-fetch": "^2.6.9",
+ "uuid": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/gaxios/node_modules/uuid": {
+ "version": "9.0.1",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/gcp-metadata": {
+ "version": "6.1.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "gaxios": "^6.0.0",
+ "json-bigint": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-uri": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.3.tgz",
+ "integrity": "sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==",
+ "dependencies": {
+ "basic-ftp": "^5.0.2",
+ "data-uri-to-buffer": "^6.0.2",
+ "debug": "^4.3.4",
+ "fs-extra": "^11.2.0"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/get-uri/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/get-uri/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/google-auth-library": {
+ "version": "9.0.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "base64-js": "^1.3.0",
+ "ecdsa-sig-formatter": "^1.0.11",
+ "gaxios": "^6.0.0",
+ "gcp-metadata": "^6.0.0",
+ "gtoken": "^7.0.0",
+ "jws": "^4.0.0",
+ "lru-cache": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/google-p12-pem": {
+ "version": "3.1.4",
+ "license": "MIT",
+ "dependencies": {
+ "node-forge": "^1.3.1"
+ },
+ "bin": {
+ "gp12-pem": "build/src/bin/gp12-pem.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/google-proto-files": {
+ "version": "3.0.3",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "protobufjs": "^7.0.0",
+ "walkdir": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/gtoken": {
+ "version": "7.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "gaxios": "^6.0.0",
+ "jws": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hexer": {
+ "version": "1.5.0",
+ "dependencies": {
+ "ansi-color": "^0.2.1",
+ "minimist": "^1.1.0",
+ "process": "^0.10.0",
+ "xtend": "^4.0.0"
+ },
+ "bin": {
+ "hexer": "cli.js"
+ },
+ "engines": {
+ "node": ">= 0.10.x"
+ }
+ },
+ "node_modules/hexer/node_modules/process": {
+ "version": "0.10.1",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "2.8.9",
+ "license": "ISC"
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "2.0.0",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": "2.0.1",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+ "dependencies": {
+ "agent-base": "^7.1.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/http-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.5",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/debug": {
+ "version": "4.3.7",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/https-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "license": "MIT"
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-in-the-middle": {
+ "version": "1.4.2",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "acorn": "^8.8.2",
+ "acorn-import-assertions": "^1.9.0",
+ "cjs-module-lexer": "^1.2.2",
+ "module-details-from-path": "^1.0.3"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "license": "ISC"
+ },
+ "node_modules/ip-address": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
+ "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
+ "dependencies": {
+ "jsbn": "1.1.0",
+ "sprintf-js": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-arguments": {
+ "version": "1.1.1",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "license": "MIT"
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.15.1",
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "license": "MIT",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.13",
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/jaeger-client": {
+ "version": "3.19.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "node-int64": "^0.4.0",
+ "opentracing": "^0.14.4",
+ "thriftrw": "^3.5.0",
+ "uuid": "^8.3.2",
+ "xorshift": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/joi": {
+ "version": "17.13.3",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.3.0",
+ "@hapi/topo": "^5.1.0",
+ "@sideway/address": "^4.1.5",
+ "@sideway/formula": "^3.0.1",
+ "@sideway/pinpoint": "^2.0.0"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "license": "MIT"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsbn": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
+ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
+ },
+ "node_modules/json-bigint": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "bignumber.js": "^9.0.0"
+ }
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "license": "MIT"
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jwa": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^2.0.0",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/kuler": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "license": "MIT"
+ },
+ "node_modules/locate-path": {
+ "version": "5.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "license": "MIT"
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "license": "MIT"
+ },
+ "node_modules/logform": {
+ "version": "2.6.1",
+ "license": "MIT",
+ "dependencies": {
+ "@colors/colors": "1.6.0",
+ "@types/triple-beam": "^1.3.2",
+ "fecha": "^4.2.0",
+ "ms": "^2.1.1",
+ "safe-stable-stringify": "^2.3.1",
+ "triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/logform/node_modules/@colors/colors": {
+ "version": "1.6.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/logform/node_modules/ms": {
+ "version": "2.1.3",
+ "license": "MIT"
+ },
+ "node_modules/long": {
+ "version": "5.2.3",
+ "license": "Apache-2.0"
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.3",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
+ },
+ "node_modules/module-details-from-path": {
+ "version": "1.0.3",
+ "license": "MIT"
+ },
+ "node_modules/ms": {
+ "version": "2.0.0",
+ "license": "MIT"
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/netmask": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
+ "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-forge": {
+ "version": "1.3.1",
+ "license": "(BSD-3-Clause OR GPL-2.0)",
+ "engines": {
+ "node": ">= 6.13.0"
+ }
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "license": "MIT"
+ },
+ "node_modules/normalize-package-data": {
+ "version": "2.5.0",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "resolve": "^1.10.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/semver": {
+ "version": "5.7.2",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "1.3.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/one-time": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "fn.name": "1.x.x"
+ }
+ },
+ "node_modules/opentracing": {
+ "version": "0.14.7",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "2.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "4.1.0",
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pac-proxy-agent": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.0.2.tgz",
+ "integrity": "sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==",
+ "dependencies": {
+ "@tootallnate/quickjs-emscripten": "^0.23.0",
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "get-uri": "^6.0.1",
+ "http-proxy-agent": "^7.0.0",
+ "https-proxy-agent": "^7.0.5",
+ "pac-resolver": "^7.0.1",
+ "socks-proxy-agent": "^8.0.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pac-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/pac-resolver": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
+ "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
+ "dependencies": {
+ "degenerator": "^5.0.0",
+ "netmask": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "license": "MIT"
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.10",
+ "license": "MIT"
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
+ },
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "license": "ISC",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.7.0",
+ "license": "MIT"
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "license": "ISC"
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/protobufjs": {
+ "version": "7.4.0",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/node": ">=13.7.0",
+ "long": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-agent": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.4.0.tgz",
+ "integrity": "sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==",
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "^4.3.4",
+ "http-proxy-agent": "^7.0.1",
+ "https-proxy-agent": "^7.0.3",
+ "lru-cache": "^7.14.1",
+ "pac-proxy-agent": "^7.0.1",
+ "proxy-from-env": "^1.1.0",
+ "socks-proxy-agent": "^8.0.2"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/proxy-agent/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "license": "MIT"
+ },
+ "node_modules/pump": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
+ "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/puppeteer": {
+ "version": "23.7.1",
+ "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-23.7.1.tgz",
+ "integrity": "sha512-jS6XehagMvxQ12etwY/4EOYZ0Sm8GAsrtGhdQn4AqpJAyHc3RYl7tGd4QYh/MmShDw8sF9FWYQqGidhoXaqokQ==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "@puppeteer/browsers": "2.4.1",
+ "chromium-bidi": "0.8.0",
+ "cosmiconfig": "^9.0.0",
+ "devtools-protocol": "0.0.1354347",
+ "puppeteer-core": "23.7.1",
+ "typed-query-selector": "^2.12.0"
+ },
+ "bin": {
+ "puppeteer": "lib/cjs/puppeteer/node/cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/puppeteer-core": {
+ "version": "23.7.1",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-23.7.1.tgz",
+ "integrity": "sha512-Om/qCZhd+HLoAr7GltrRAZpS3uOXwHu7tXAoDbNcJADHjG2zeAlDArgyIPXYGG4QB/EQUHk13Q6RklNxGM73Pg==",
+ "dependencies": {
+ "@puppeteer/browsers": "2.4.1",
+ "chromium-bidi": "0.8.0",
+ "debug": "^4.3.7",
+ "devtools-protocol": "0.0.1354347",
+ "typed-query-selector": "^2.12.0",
+ "ws": "^8.18.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/puppeteer-core/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/qs": {
+ "version": "6.13.0",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.0.6"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/queue-tick": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz",
+ "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.2",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "http-errors": "2.0.0",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/read-pkg": {
+ "version": "5.2.0",
+ "license": "MIT",
+ "dependencies": {
+ "@types/normalize-package-data": "^2.4.0",
+ "normalize-package-data": "^2.5.0",
+ "parse-json": "^5.0.0",
+ "type-fest": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/read-pkg-up": {
+ "version": "7.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/read-pkg/node_modules/type-fest": {
+ "version": "0.6.0",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-in-the-middle": {
+ "version": "7.4.0",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.5",
+ "module-details-from-path": "^1.0.3",
+ "resolve": "^1.22.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/require-in-the-middle/node_modules/debug": {
+ "version": "4.3.7",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/require-in-the-middle/node_modules/ms": {
+ "version": "2.1.3",
+ "license": "MIT"
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/safe-stable-stringify": {
+ "version": "2.5.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.19.0",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/encodeurl": {
+ "version": "1.0.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/send/node_modules/ms": {
+ "version": "2.1.3",
+ "license": "MIT"
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.2",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "0.19.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "license": "ISC"
+ },
+ "node_modules/shimmer": {
+ "version": "1.2.1",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "license": "MIT",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/simple-swizzle/node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "license": "MIT"
+ },
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.3",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
+ "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
+ "dependencies": {
+ "ip-address": "^9.0.5",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz",
+ "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==",
+ "dependencies": {
+ "agent-base": "^7.1.1",
+ "debug": "^4.3.4",
+ "socks": "^2.8.3"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/socks-proxy-agent/node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/socks-proxy-agent/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "optional": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.5.0",
+ "license": "CC-BY-3.0"
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.20",
+ "license": "CC0-1.0"
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
+ "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
+ },
+ "node_modules/stack-trace": {
+ "version": "0.0.10",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "license": "MIT"
+ },
+ "node_modules/statuses": {
+ "version": "2.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/streamx": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz",
+ "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==",
+ "dependencies": {
+ "fast-fifo": "^1.3.2",
+ "queue-tick": "^1.0.1",
+ "text-decoder": "^1.1.0"
+ },
+ "optionalDependencies": {
+ "bare-events": "^2.2.0"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-template": {
+ "version": "0.2.1"
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz",
+ "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==",
+ "dependencies": {
+ "pump": "^3.0.0",
+ "tar-stream": "^3.1.5"
+ },
+ "optionalDependencies": {
+ "bare-fs": "^2.1.1",
+ "bare-path": "^2.1.0"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
+ "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
+ "dependencies": {
+ "b4a": "^1.6.4",
+ "fast-fifo": "^1.2.0",
+ "streamx": "^2.15.0"
+ }
+ },
+ "node_modules/text-decoder": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.1.tgz",
+ "integrity": "sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ=="
+ },
+ "node_modules/text-hex": {
+ "version": "1.0.0",
+ "license": "MIT"
+ },
+ "node_modules/thriftrw": {
+ "version": "3.11.4",
+ "dependencies": {
+ "bufrw": "^1.2.1",
+ "error": "7.0.2",
+ "long": "^2.4.0"
+ },
+ "bin": {
+ "thrift2json": "thrift2json.js"
+ },
+ "engines": {
+ "node": ">= 0.10.x"
+ }
+ },
+ "node_modules/thriftrw/node_modules/long": {
+ "version": "2.4.0",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "license": "MIT"
+ },
+ "node_modules/triple-beam": {
+ "version": "1.4.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/ts-poet": {
+ "version": "6.9.0",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "dprint-node": "^1.0.8"
+ }
+ },
+ "node_modules/ts-proto": {
+ "version": "1.148.1",
+ "license": "ISC",
+ "dependencies": {
+ "@types/object-hash": "^1.3.0",
+ "case-anything": "^2.1.10",
+ "dataloader": "^1.4.0",
+ "object-hash": "^1.3.1",
+ "protobufjs": "^6.11.3",
+ "ts-poet": "^6.4.1",
+ "ts-proto-descriptors": "1.9.0"
+ },
+ "bin": {
+ "protoc-gen-ts_proto": "protoc-gen-ts_proto"
+ }
+ },
+ "node_modules/ts-proto-descriptors": {
+ "version": "1.9.0",
+ "license": "ISC",
+ "dependencies": {
+ "long": "^4.0.0",
+ "protobufjs": "^6.8.8"
+ }
+ },
+ "node_modules/ts-proto-descriptors/node_modules/long": {
+ "version": "4.0.0",
+ "license": "Apache-2.0"
+ },
+ "node_modules/ts-proto-descriptors/node_modules/protobufjs": {
+ "version": "6.11.4",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/long": "^4.0.1",
+ "@types/node": ">=13.7.0",
+ "long": "^4.0.0"
+ },
+ "bin": {
+ "pbjs": "bin/pbjs",
+ "pbts": "bin/pbts"
+ }
+ },
+ "node_modules/ts-proto/node_modules/long": {
+ "version": "4.0.0",
+ "license": "Apache-2.0"
+ },
+ "node_modules/ts-proto/node_modules/protobufjs": {
+ "version": "6.11.4",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.4",
+ "@protobufjs/eventemitter": "^1.1.0",
+ "@protobufjs/fetch": "^1.1.0",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/inquire": "^1.1.0",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.0",
+ "@types/long": "^4.0.1",
+ "@types/node": ">=13.7.0",
+ "long": "^4.0.0"
+ },
+ "bin": {
+ "pbjs": "bin/pbjs",
+ "pbts": "bin/pbts"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ },
+ "node_modules/type-fest": {
+ "version": "0.8.1",
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typed-query-selector": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.0.tgz",
+ "integrity": "sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg=="
+ },
+ "node_modules/unbzip2-stream": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
+ "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
+ "dependencies": {
+ "buffer": "^5.2.1",
+ "through": "^2.3.8"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "license": "MIT"
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/urlpattern-polyfill": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz",
+ "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg=="
+ },
+ "node_modules/util": {
+ "version": "0.12.5",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "is-typed-array": "^1.1.3",
+ "which-typed-array": "^1.1.2"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "license": "MIT"
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/walkdir": {
+ "version": "0.4.1",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.15",
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/winston": {
+ "version": "3.10.0",
+ "license": "MIT",
+ "dependencies": {
+ "@colors/colors": "1.5.0",
+ "@dabh/diagnostics": "^2.0.2",
+ "async": "^3.2.3",
+ "is-stream": "^2.0.0",
+ "logform": "^2.4.0",
+ "one-time": "^1.0.0",
+ "readable-stream": "^3.4.0",
+ "safe-stable-stringify": "^2.3.1",
+ "stack-trace": "0.0.x",
+ "triple-beam": "^1.3.0",
+ "winston-transport": "^4.5.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/winston-transport": {
+ "version": "4.8.0",
+ "license": "MIT",
+ "dependencies": {
+ "logform": "^2.6.1",
+ "readable-stream": "^4.5.2",
+ "triple-beam": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/winston-transport/node_modules/buffer": {
+ "version": "6.0.3",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/winston-transport/node_modules/readable-stream": {
+ "version": "4.5.2",
+ "license": "MIT",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-convert": {
+ "version": "2.0.1",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/color-name": {
+ "version": "1.1.4",
+ "license": "MIT"
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/ws": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xorshift": {
+ "version": "1.2.0",
+ "license": "MIT"
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "license": "ISC"
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "license": "MIT",
+ "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"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.23.8",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
+ "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ }
+ }
+}
diff --git a/monitoring/puppeteer-nodejs/package.json b/monitoring/puppeteer-nodejs/package.json
new file mode 100644
index 00000000..020095ae
--- /dev/null
+++ b/monitoring/puppeteer-nodejs/package.json
@@ -0,0 +1,19 @@
+{
+ "type": "module",
+ "name": "generic-puppeteer-nodejs",
+ "version": "1.0.0",
+ "description": "Contains functions for privacy sandbox demos synthetic monitoring",
+ "main": "index.js",
+ "scripts": {
+ "gcp-build": "node node_modules/puppeteer/install.mjs",
+ "start": "functions-framework --target=$npm_config_target"
+ },
+ "dependencies": {
+ "@google-cloud/functions-framework": "^3.4.2",
+ "@google-cloud/synthetics-sdk-api": "^0.6.0",
+ "axios": "^1.7.7",
+ "puppeteer": "^23.7.1"
+ },
+ "license": "Apache-2.0",
+ "author": "Google Inc."
+}
diff --git a/nginx/nginx.conf b/nginx/nginx.conf
index cd1b8210..9f7cd5c5 100644
--- a/nginx/nginx.conf
+++ b/nginx/nginx.conf
@@ -187,66 +187,49 @@ server {
server {
listen 443 ssl;
- server_name ${TOPICS_MOTO_HOST};
+ server_name ${MOTO_NEWS_HOST};
- ssl_certificate /cert/${TOPICS_MOTO_HOST}.pem;
- ssl_certificate_key /cert/${TOPICS_MOTO_HOST}-key.pem;
+ ssl_certificate /cert/${MOTO_NEWS_HOST}.pem;
+ ssl_certificate_key /cert/${MOTO_NEWS_HOST}-key.pem;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location / {
- proxy_pass http://topics:${PORT}/;
- }
-}
-
-server {
- listen 443 ssl;
- server_name ${TOPICS_GARDENING_HOST};
-
- ssl_certificate /cert/${TOPICS_GARDENING_HOST}.pem;
- ssl_certificate_key /cert/${TOPICS_GARDENING_HOST}-key.pem;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- location / {
- proxy_pass http://topics:${PORT}/;
+ proxy_pass http://news:${PORT}/;
}
}
server {
listen 443 ssl;
- server_name ${TOPICS_SOCCER_HOST};
+ server_name ${GARDENING_NEWS_HOST};
- ssl_certificate /cert/${TOPICS_SOCCER_HOST}.pem;
- ssl_certificate_key /cert/${TOPICS_SOCCER_HOST}-key.pem;
+ ssl_certificate /cert/${GARDENING_NEWS_HOST}.pem;
+ ssl_certificate_key /cert/${GARDENING_NEWS_HOST}-key.pem;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location / {
- proxy_pass http://topics:${PORT}/;
+ proxy_pass http://news:${PORT}/;
}
}
server {
listen 443 ssl;
- server_name ${TOPICS_SERVER_HOST};
-
- ssl_certificate /cert/${TOPICS_SERVER_HOST}.pem;
- ssl_certificate_key /cert/${TOPICS_SERVER_HOST}-key.pem;
+ server_name ${SOCCER_NEWS_HOST};
+ ssl_certificate /cert/${SOCCER_NEWS_HOST}.pem;
+ ssl_certificate_key /cert/${SOCCER_NEWS_HOST}-key.pem;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location / {
- proxy_pass http://topics-server:${PORT}/;
+ proxy_pass http://news:${PORT}/;
}
}
diff --git a/package.json b/package.json
index 6b2f46f4..e600ea86 100644
--- a/package.json
+++ b/package.json
@@ -9,8 +9,8 @@
"build": "docker-compose build",
"docker": "docker-compose build && docker-compose up",
"deploy": "./scripts/cloudrun_deploy.sh && ./scripts/firebase_deploy.sh",
- "clean": "docker-compose rm -f && docker volume prune -f && docker image prune -f && docker rmi -f $(docker images -q)",
- "fmt": "prettier --write ."
+ "clean": "docker-compose rm -f && docker volume prune -f && docker image prune -f && docker rmi -f $(docker images -q) && docker-compose down -v",
+ "fmt": "pre-commit run --all-files"
},
"devDependencies": {
"firebase-tools": "^11.23.0",
diff --git a/scripts/cloudrun_deploy.sh b/scripts/cloudrun_deploy.sh
index d1ada036..cbbe9d80 100755
--- a/scripts/cloudrun_deploy.sh
+++ b/scripts/cloudrun_deploy.sh
@@ -15,6 +15,7 @@
# limitations under the License.
# load env vars
+source cicd/.env.dev
source .env.deploy
# setup Google Cloud SDK project
diff --git a/scripts/cloudrun_setup.sh b/scripts/cloudrun_setup.sh
index 9c32000d..bfe31208 100755
--- a/scripts/cloudrun_setup.sh
+++ b/scripts/cloudrun_setup.sh
@@ -22,7 +22,7 @@ gcloud config set project $GCP_PROJECT_NAME
gcloud config get-value project
# Enable Cloud Run API
-gcloud services enable run.googleapis.com cloudbuild.googleapis.com artifactregistry.googleapis.com
+gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com logging.googleapis.com pubsub.googleapis.com run.googleapis.com
# make the default region us-central1
gcloud config set run/region us-central1
diff --git a/scripts/monitoring_deploy.sh b/scripts/monitoring_deploy.sh
new file mode 100755
index 00000000..615a72f8
--- /dev/null
+++ b/scripts/monitoring_deploy.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env zsh
+
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# References :
+# - https://cloud.google.com/monitoring/synthetic-monitors/create#monitoring_synthetic_monitor_create-gcloud
+
+# Run this script from the root of the project directory
+# ./scripts/monitoring_deploy.sh
+
+# NOTE :
+# Everytime you run this script, it will redeploy the monitoring function for each and every use cases
+# Cloud Run function will build and deploy each of the function individually and it will take time
+# This is good when you are first setting up monitoring functions but not if you are only updating one function,
+# We recommend you to use one of the example command line below to deploy the updated function only.
+
+
+# load env vars
+source .env.deploy
+source .demos
+
+# setup Google Cloud SDK project
+gcloud config set project $GCP_PROJECT_NAME
+gcloud config get-value project
+
+# Read env vars to pass to Cloud Functions
+ENV_VARS=$(cat ${ENV_FILE} | grep "=" | grep -v "^PORT=" | sed '/^$/d' | tr "\n" "@")
+echo ${ENV_VARS}
+
+
+# Iterate through the use cases to deploy Cloud Functions
+for demo in ${DEMOS}; do
+
+ function=monitor-${demo}
+ entrypoint="${DEMO_MONITORING_ENTRYPOINT[$demo]}"
+
+ # deploy monitoring function
+ gcloud functions deploy ${function} --gen2 --runtime=nodejs18 --region=${GCP_REGION} --source="monitoring/puppeteer-nodejs/" --entry-point=${entrypoint} --memory=2G --timeout=60 --trigger-http --ingress-settings=internal-only --no-allow-unauthenticated --set-env-vars "^@^${ENV_VARS}"
+done
+
+
+# Deploy functions to be used by Cloud Monitoring synethic monitor (use these command individually when you want to update only one function)
+
+# gcloud functions deploy monitor-uc-single-touch-conversion --gen2 --runtime=nodejs18 --region="us-central1" --source="monitoring/puppeteer-nodejs/" --entry-point=MonitorUcSingleTouchConversion --memory=2G --timeout=60 --trigger-http --ingress-settings=internal-only --no-allow-unauthenticated
+# gcloud functions deploy monitor-uc-remarketing --gen2 --runtime=nodejs18 --region="us-central1" --source="monitoring/puppeteer-nodejs/" --entry-point=MonitorUcRemarketing --memory=2G --timeout=60 --trigger-http --ingress-settings=internal-only --no-allow-unauthenticated
+# gcloud functions deploy monitor-uc-vast-video-paapi --gen2 --runtime=nodejs18 --region="us-central1" --source="monitoring/puppeteer-nodejs/" --entry-point=MonitorUcVastVideoPaapi --memory=2G --timeout=60 --trigger-http --ingress-settings=internal-only --no-allow-unauthenticated
+# gcloud functions deploy monitor-uc-video-multi-seller-seq-auction-paapi --gen2 --runtime=nodejs18 --region="us-central1" --source="monitoring/puppeteer-nodejs/" --entry-point=MonitorUcVideoMultiSellerSeqAuctionPaapi --memory=2G --timeout=60 --trigger-http --ingress-settings=internal-only --no-allow-unauthenticated
+
+# List all functions
+# gcloud functions list
+
+# find the fully-qualified name for a specific Cloud Run Function
+# gcloud functions describe monitor-uc-single-touch-conversion --format='value(name)'
+
+# Print Cloud Run Function URL
+# gcloud run services describe monitor-uc-single-touch-conversion --format='value(status.url)'
diff --git a/scripts/monitoring_setup.sh b/scripts/monitoring_setup.sh
new file mode 100755
index 00000000..32a92562
--- /dev/null
+++ b/scripts/monitoring_setup.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env zsh
+
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# evaluate .env file
+source .env.deploy
+
+# setup Google Cloud SDK project
+gcloud config set project $GCP_PROJECT_NAME
+gcloud config get-value project
+
+# Enable APIs required for Cloud Monitoring Synthetic Monitor
+# See : https://cloud.google.com/monitoring/synthetic-monitors/create#monitoring_synthetic_monitor_create-console
+gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com cloudfunctions.googleapis.com logging.googleapis.com pubsub.googleapis.com run.googleapis.com
+
+# make the default region us-central1
+gcloud config set run/region us-central1
+
+
+
diff --git a/scripts/monitoring_uptime.sh b/scripts/monitoring_uptime.sh
new file mode 100755
index 00000000..d968b63f
--- /dev/null
+++ b/scripts/monitoring_uptime.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env zsh
+
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# References :
+# - https://cloud.google.com/monitoring/uptime-checks
+
+# Run this script from the root of the project directory
+# ./scripts/monitoring_uptime.sh
+
+# NOTE :
+# This script is not idempotent. running it twice will create additional monitoring uptime checks without overriding or deleting the existing ones.
+# You can use the script at the bottom to remove all existing checks at your own responsibility.
+
+# load env vars
+source .env.deploy
+source ${ENV_FILE}
+source .demos
+
+# setup Google Cloud SDK project
+gcloud config set project $GCP_PROJECT_NAME
+gcloud config get-value project
+
+
+# Iterate through the use cases to setup Synthetic Monitors
+for demo in ${DEMOS}; do
+
+ function=monitor-${demo}
+ title="Monitor Use Case : ${DEMO_TITLE[$demo]}"
+
+ # get function full name
+ function_name=$(gcloud functions describe ${function} --format='value(name)')
+
+ # Setup synthetic monitor with a check frequency of 10 min and a timeout of 60 sec
+ gcloud monitoring uptime create "${title}" --synthetic-target="${function_name}" --period=10 --timeout=60
+
+done
+
+# Iterate through the services to setup Uptime checks
+# for service in $SERVICES; do
+# echo "Setup Monitoring Uptime Check for Cloud Run Service \"${service}\""
+# # Setup a monitoring uptime check frequency of 10 min and a timeout of 10 sec
+# gcloud monitoring uptime create "Uptime Check for Cloud Run ${service} service" --protocol=https --request-method=get --status-classes=2xx --period=10 --timeout=10 --resource-type=cloud-run-revision --resource-labels=service_name=${service} --resource-labels=project_id=${GCP_PROJECT_NAME} --resource-labels=location=${GCP_REGION}
+# done
+
+
+# List uptime check ids
+# gcloud monitoring uptime list-configs --format='value(name)'
+
+# delete uptime check
+# gcloud monitoring uptime delete CHECK_ID
+
+# delete all uptime check
+# for check_id in $(gcloud monitoring uptime list-configs --format='value(name)'); do
+# gcloud monitoring uptime delete $check_id
+# done
diff --git a/services/ad-server/.gitignore b/services/ad-server/.gitignore
deleted file mode 100644
index 0011583b..00000000
--- a/services/ad-server/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-**/*.js
-**/*.css
-!**/*.tailwind.css
-!src/public/**/*.js
\ No newline at end of file
diff --git a/services/ad-server/.prettierignore b/services/ad-server/.prettierignore
deleted file mode 100644
index cce52178..00000000
--- a/services/ad-server/.prettierignore
+++ /dev/null
@@ -1,5 +0,0 @@
-# Ignore artifacts:
-build
-node_modules
-*.ejs
-*.js
\ No newline at end of file
diff --git a/services/ad-server/package-lock.json b/services/ad-server/package-lock.json
deleted file mode 100644
index b515f4b8..00000000
--- a/services/ad-server/package-lock.json
+++ /dev/null
@@ -1,2881 +0,0 @@
-{
- "name": "server",
- "version": "0.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "server",
- "version": "0.0.0",
- "license": "apache-2.0",
- "dependencies": {
- "ejs": "^3.1.9",
- "express": "^4.18.2"
- },
- "devDependencies": {
- "@types/express": "^4.17.17",
- "@types/node": "^20.4.2",
- "npm-run-all": "^4.1.5",
- "prettier": "^3.0.0",
- "tailwindcss": "^3.3.2",
- "ts-node": "^10.9.1",
- "typescript": "^5.1.6"
- }
- },
- "node_modules/@alloc/quick-lru": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@cspotcode/source-map-support": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "dev": true,
- "dependencies": {
- "@jridgewell/trace-mapping": "0.3.9"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
- "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/set-array": "^1.0.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
- "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/set-array": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.14",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
- "dev": true
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@tsconfig/node10": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
- "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
- "dev": true
- },
- "node_modules/@tsconfig/node12": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
- "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "dev": true
- },
- "node_modules/@tsconfig/node14": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
- "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "dev": true
- },
- "node_modules/@tsconfig/node16": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
- "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
- "dev": true
- },
- "node_modules/@types/body-parser": {
- "version": "1.19.2",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
- "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
- "dev": true,
- "dependencies": {
- "@types/connect": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/connect": {
- "version": "3.4.35",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
- "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
- "dev": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/express": {
- "version": "4.17.17",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
- "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==",
- "dev": true,
- "dependencies": {
- "@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.33",
- "@types/qs": "*",
- "@types/serve-static": "*"
- }
- },
- "node_modules/@types/express-serve-static-core": {
- "version": "4.17.33",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz",
- "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==",
- "dev": true,
- "dependencies": {
- "@types/node": "*",
- "@types/qs": "*",
- "@types/range-parser": "*"
- }
- },
- "node_modules/@types/mime": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
- "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==",
- "dev": true
- },
- "node_modules/@types/node": {
- "version": "20.4.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz",
- "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==",
- "dev": true
- },
- "node_modules/@types/qs": {
- "version": "6.9.7",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
- "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
- "dev": true
- },
- "node_modules/@types/range-parser": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
- "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
- "dev": true
- },
- "node_modules/@types/serve-static": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz",
- "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==",
- "dev": true,
- "dependencies": {
- "@types/mime": "*",
- "@types/node": "*"
- }
- },
- "node_modules/accepts": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
- "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/any-promise": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/arg": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
- "dev": true
- },
- "node_modules/array-flatten": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
- },
- "node_modules/async": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
- "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
- },
- "node_modules/binary-extensions": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/body-parser": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
- "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
- "dependencies": {
- "bytes": "3.1.2",
- "content-type": "~1.0.4",
- "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.1",
- "type-is": "~1.6.18",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "dependencies": {
- "fill-range": "^7.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "dependencies": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/camelcase-css": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
- "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/chokidar": {
- "version": "3.5.3",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
- "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
- "dev": true,
- "funding": [
- {
- "type": "individual",
- "url": "https://paulmillr.com/funding/"
- }
- ],
- "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"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/chokidar/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
- },
- "node_modules/commander": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
- },
- "node_modules/content-disposition": {
- "version": "0.5.4",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
- "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
- "dependencies": {
- "safe-buffer": "5.2.1"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
- },
- "node_modules/create-require": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
- "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "dev": true
- },
- "node_modules/cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
- "dev": true,
- "dependencies": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- },
- "engines": {
- "node": ">=4.8"
- }
- },
- "node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
- "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
- "dev": true,
- "dependencies": {
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/destroy": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
- "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/didyoumean": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
- "dev": true
- },
- "node_modules/diff": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
- "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "dev": true,
- "engines": {
- "node": ">=0.3.1"
- }
- },
- "node_modules/dlv": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
- "dev": true
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
- },
- "node_modules/ejs": {
- "version": "3.1.9",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
- "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
- "dependencies": {
- "jake": "^10.8.5"
- },
- "bin": {
- "ejs": "bin/cli.js"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
- "dev": true,
- "dependencies": {
- "is-arrayish": "^0.2.1"
- }
- },
- "node_modules/es-abstract": {
- "version": "1.21.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz",
- "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "es-set-tostringtag": "^2.0.1",
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "function.prototype.name": "^1.1.5",
- "get-intrinsic": "^1.1.3",
- "get-symbol-description": "^1.0.0",
- "globalthis": "^1.0.3",
- "gopd": "^1.0.1",
- "has": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.4",
- "is-array-buffer": "^3.0.1",
- "is-callable": "^1.2.7",
- "is-negative-zero": "^2.0.2",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "is-string": "^1.0.7",
- "is-typed-array": "^1.1.10",
- "is-weakref": "^1.0.2",
- "object-inspect": "^1.12.2",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.4.3",
- "safe-regex-test": "^1.0.0",
- "string.prototype.trimend": "^1.0.6",
- "string.prototype.trimstart": "^1.0.6",
- "typed-array-length": "^1.0.4",
- "unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.9"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
- "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3",
- "has": "^1.0.3",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
- },
- "node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/express": {
- "version": "4.18.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
- "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
- "dependencies": {
- "accepts": "~1.3.8",
- "array-flatten": "1.1.1",
- "body-parser": "1.20.1",
- "content-disposition": "0.5.4",
- "content-type": "~1.0.4",
- "cookie": "0.5.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"
- },
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/fast-glob": {
- "version": "3.2.12",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
- "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/filelist": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
- "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
- "dependencies": {
- "minimatch": "^5.0.1"
- }
- },
- "node_modules/filelist/node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/filelist/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/finalhandler": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
- "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"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.3"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
- "node_modules/fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
- },
- "node_modules/function.prototype.name": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
- "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.0",
- "functions-have-names": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
- "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
- "dependencies": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/glob": {
- "version": "7.1.6",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
- "dev": true,
- "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"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/globalthis": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
- "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
- "dev": true,
- "dependencies": {
- "define-properties": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.10",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
- "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
- "dev": true
- },
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/has-bigints": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
- "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hosted-git-info": {
- "version": "2.8.9",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
- "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
- "dev": true
- },
- "node_modules/http-errors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
- "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"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/internal-slot": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
- "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.2.0",
- "has": "^1.0.3",
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/is-array-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz",
- "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
- "is-typed-array": "^1.1.10"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "dev": true
- },
- "node_modules/is-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
- "dev": true,
- "dependencies": {
- "has-bigints": "^1.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-boolean-object": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
- "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
- "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
- "dev": true,
- "dependencies": {
- "has": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-date-object": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
- "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
- "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-number-object": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
- "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-regex": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
- "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-string": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
- "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
- "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-typed-array": {
- "version": "1.1.10",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
- "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakref": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
- "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "node_modules/jake": {
- "version": "10.8.5",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
- "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
- "dependencies": {
- "async": "^3.2.3",
- "chalk": "^4.0.2",
- "filelist": "^1.0.1",
- "minimatch": "^3.0.4"
- },
- "bin": {
- "jake": "bin/cli.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/jiti": {
- "version": "1.19.1",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
- "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==",
- "dev": true,
- "bin": {
- "jiti": "bin/jiti.js"
- }
- },
- "node_modules/json-parse-better-errors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
- "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
- "dev": true
- },
- "node_modules/lilconfig": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
- },
- "node_modules/load-json-file": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
- "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^4.0.0",
- "pify": "^3.0.0",
- "strip-bom": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/make-error": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
- "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "dev": true
- },
- "node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/memorystream": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
- "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
- "dev": true,
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/methods": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
- },
- "node_modules/mz": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
- "dependencies": {
- "any-promise": "^1.0.0",
- "object-assign": "^4.0.1",
- "thenify-all": "^1.0.0"
- }
- },
- "node_modules/nanoid": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/nice-try": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
- "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
- "dev": true
- },
- "node_modules/normalize-package-data": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
- "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
- "dev": true,
- "dependencies": {
- "hosted-git-info": "^2.1.4",
- "resolve": "^1.10.0",
- "semver": "2 || 3 || 4 || 5",
- "validate-npm-package-license": "^3.0.1"
- }
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/npm-run-all": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
- "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "chalk": "^2.4.1",
- "cross-spawn": "^6.0.5",
- "memorystream": "^0.3.1",
- "minimatch": "^3.0.4",
- "pidtree": "^0.3.0",
- "read-pkg": "^3.0.0",
- "shell-quote": "^1.6.1",
- "string.prototype.padend": "^3.0.0"
- },
- "bin": {
- "npm-run-all": "bin/npm-run-all/index.js",
- "run-p": "bin/run-p/index.js",
- "run-s": "bin/run-s/index.js"
- },
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/npm-run-all/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-run-all/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-run-all/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/npm-run-all/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/npm-run-all/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/npm-run-all/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-hash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
- "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.assign": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
- "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "has-symbols": "^1.0.3",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
- "dev": true,
- "dependencies": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "node_modules/path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
- },
- "node_modules/path-type": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
- "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
- "dev": true,
- "dependencies": {
- "pify": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pidtree": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
- "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
- "dev": true,
- "bin": {
- "pidtree": "bin/pidtree.js"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/pirates": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
- "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.25",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.25.tgz",
- "integrity": "sha512-7taJ/8t2av0Z+sQEvNzCkpDynl0tX3uJMCODi6nT3PfASC7dYCWV9aQ+uiCf+KBD4SEFcu+GvJdGdwzQ6OSjCw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.6",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.2"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss-import": {
- "version": "15.1.0",
- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
- "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
- "dev": true,
- "dependencies": {
- "postcss-value-parser": "^4.0.0",
- "read-cache": "^1.0.0",
- "resolve": "^1.1.7"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "postcss": "^8.0.0"
- }
- },
- "node_modules/postcss-js": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
- "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
- "dev": true,
- "dependencies": {
- "camelcase-css": "^2.0.1"
- },
- "engines": {
- "node": "^12 || ^14 || >= 16"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": "^8.4.21"
- }
- },
- "node_modules/postcss-load-config": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
- "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
- "dev": true,
- "dependencies": {
- "lilconfig": "^2.0.5",
- "yaml": "^2.1.1"
- },
- "engines": {
- "node": ">= 14"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": ">=8.0.9",
- "ts-node": ">=9.0.0"
- },
- "peerDependenciesMeta": {
- "postcss": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- }
- }
- },
- "node_modules/postcss-nested": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
- "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
- "dev": true,
- "dependencies": {
- "postcss-selector-parser": "^6.0.11"
- },
- "engines": {
- "node": ">=12.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": "^8.2.14"
- }
- },
- "node_modules/postcss-selector-parser": {
- "version": "6.0.13",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
- "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
- "dev": true,
- "dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true
- },
- "node_modules/prettier": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
- "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
- "dev": true,
- "bin": {
- "prettier": "bin/prettier.cjs"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
- }
- },
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/qs": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
- "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
- "dependencies": {
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
- "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
- "dependencies": {
- "bytes": "3.1.2",
- "http-errors": "2.0.0",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/read-cache": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "dev": true,
- "dependencies": {
- "pify": "^2.3.0"
- }
- },
- "node_modules/read-cache/node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/read-pkg": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
- "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
- "dev": true,
- "dependencies": {
- "load-json-file": "^4.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/regexp.prototype.flags": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
- "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "functions-have-names": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.2",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
- "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.11.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/safe-regex-test": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
- "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
- "is-regex": "^1.1.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
- },
- "node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true,
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/send": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
- "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"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
- },
- "node_modules/serve-static": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
- "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
- "dependencies": {
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "0.18.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
- },
- "node_modules/shebang-command": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
- "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
- "dev": true,
- "dependencies": {
- "shebang-regex": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/shebang-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
- "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/shell-quote": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz",
- "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
- "dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/spdx-correct": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
- "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
- "dev": true,
- "dependencies": {
- "spdx-expression-parse": "^3.0.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "node_modules/spdx-exceptions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
- "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
- "dev": true
- },
- "node_modules/spdx-expression-parse": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
- "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
- "dev": true,
- "dependencies": {
- "spdx-exceptions": "^2.1.0",
- "spdx-license-ids": "^3.0.0"
- }
- },
- "node_modules/spdx-license-ids": {
- "version": "3.0.12",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz",
- "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==",
- "dev": true
- },
- "node_modules/statuses": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
- "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/string.prototype.padend": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz",
- "integrity": "sha512-67otBXoksdjsnXXRUq+KMVTdlVRZ2af422Y0aTyTjVaoQkGr3mxl2Bc5emi7dOQ3OGVVQQskmLEWwFXwommpNw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimend": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
- "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
- "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/sucrase": {
- "version": "3.32.0",
- "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.32.0.tgz",
- "integrity": "sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.2",
- "commander": "^4.0.0",
- "glob": "7.1.6",
- "lines-and-columns": "^1.1.6",
- "mz": "^2.7.0",
- "pirates": "^4.0.1",
- "ts-interface-checker": "^0.1.9"
- },
- "bin": {
- "sucrase": "bin/sucrase",
- "sucrase-node": "bin/sucrase-node"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/tailwindcss": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz",
- "integrity": "sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==",
- "dev": true,
- "dependencies": {
- "@alloc/quick-lru": "^5.2.0",
- "arg": "^5.0.2",
- "chokidar": "^3.5.3",
- "didyoumean": "^1.2.2",
- "dlv": "^1.1.3",
- "fast-glob": "^3.2.12",
- "glob-parent": "^6.0.2",
- "is-glob": "^4.0.3",
- "jiti": "^1.18.2",
- "lilconfig": "^2.1.0",
- "micromatch": "^4.0.5",
- "normalize-path": "^3.0.0",
- "object-hash": "^3.0.0",
- "picocolors": "^1.0.0",
- "postcss": "^8.4.23",
- "postcss-import": "^15.1.0",
- "postcss-js": "^4.0.1",
- "postcss-load-config": "^4.0.1",
- "postcss-nested": "^6.0.1",
- "postcss-selector-parser": "^6.0.11",
- "postcss-value-parser": "^4.2.0",
- "resolve": "^1.22.2",
- "sucrase": "^3.32.0"
- },
- "bin": {
- "tailwind": "lib/cli.js",
- "tailwindcss": "lib/cli.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/thenify": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
- "dependencies": {
- "any-promise": "^1.0.0"
- }
- },
- "node_modules/thenify-all": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
- "dependencies": {
- "thenify": ">= 3.1.0 < 4"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/ts-interface-checker": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
- "dev": true
- },
- "node_modules/ts-node": {
- "version": "10.9.1",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
- "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
- "dev": true,
- "dependencies": {
- "@cspotcode/source-map-support": "^0.8.0",
- "@tsconfig/node10": "^1.0.7",
- "@tsconfig/node12": "^1.0.7",
- "@tsconfig/node14": "^1.0.0",
- "@tsconfig/node16": "^1.0.2",
- "acorn": "^8.4.1",
- "acorn-walk": "^8.1.1",
- "arg": "^4.1.0",
- "create-require": "^1.1.0",
- "diff": "^4.0.1",
- "make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.1",
- "yn": "3.1.1"
- },
- "bin": {
- "ts-node": "dist/bin.js",
- "ts-node-cwd": "dist/bin-cwd.js",
- "ts-node-esm": "dist/bin-esm.js",
- "ts-node-script": "dist/bin-script.js",
- "ts-node-transpile-only": "dist/bin-transpile.js",
- "ts-script": "dist/bin-script-deprecated.js"
- },
- "peerDependencies": {
- "@swc/core": ">=1.2.50",
- "@swc/wasm": ">=1.2.50",
- "@types/node": "*",
- "typescript": ">=2.7"
- },
- "peerDependenciesMeta": {
- "@swc/core": {
- "optional": true
- },
- "@swc/wasm": {
- "optional": true
- }
- }
- },
- "node_modules/ts-node/node_modules/acorn": {
- "version": "8.8.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
- "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/ts-node/node_modules/acorn-walk": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
- "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/ts-node/node_modules/arg": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "dev": true
- },
- "node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/typed-array-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
- "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "is-typed-array": "^1.1.9"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typescript": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
- "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
- "dev": true,
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/unbox-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
- "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-bigints": "^1.0.2",
- "has-symbols": "^1.0.3",
- "which-boxed-primitive": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
- },
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/v8-compile-cache-lib": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
- "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "dev": true
- },
- "node_modules/validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
- "dependencies": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
- }
- },
- "node_modules/which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
- "dev": true,
- "dependencies": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-typed-array": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
- "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
- "node_modules/yaml": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz",
- "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==",
- "dev": true,
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/yn": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
- "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- }
- }
-}
diff --git a/services/ad-server/package.json b/services/ad-server/package.json
deleted file mode 100644
index 9af11659..00000000
--- a/services/ad-server/package.json
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- "name": "server",
- "version": "0.0.0",
- "license": "apache-2.0",
- "main": "index.js",
- "type": "module",
- "scripts": {
- "start": "npm run build && node ./src/index.js",
- "build": "npm-run-all -p build:*",
- "build:tsc": "tsc",
- "build:css": "npx tailwindcss -i ./src/public/css/global.tailwind.css -o ./src/public/css/global.css",
- "dev": "npm-run-all -p start \"build:css -- --watch\"",
- "ncu": "npx npm-check-updates -u"
- },
- "dependencies": {
- "ejs": "^3.1.9",
- "express": "^4.18.2"
- },
- "devDependencies": {
- "@types/express": "^4.17.17",
- "@types/node": "^20.4.2",
- "npm-run-all": "^4.1.5",
- "prettier": "^3.0.0",
- "tailwindcss": "^3.3.2",
- "ts-node": "^10.9.1",
- "typescript": "^5.1.6"
- }
-}
diff --git a/services/ad-server/src/index.ts b/services/ad-server/src/index.ts
deleted file mode 100644
index e5149982..00000000
--- a/services/ad-server/src/index.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- Copyright 2022 Google LLC
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-import express, {Application, Request, Response} from 'express';
-
-const {PORT, SSP_A_URI, SSP_B_URI} = process.env;
-
-const app: Application = express();
-
-app.use((req, res, next) => {
- res.setHeader('Observe-Browsing-Topics', '?1');
- res.setHeader('Access-Control-Allow-Origin', '*');
- next();
-});
-
-app.use(
- express.static('src/public', {
- setHeaders: (res, path) => {
- const shouldAddAuctionHeader = [
- 'decision-logic.js',
- 'trusted.json',
- 'direct.json',
- ].some((fileName) => path.includes(fileName));
-
- if (shouldAddAuctionHeader) {
- return res.set('Ad-Auction-Allowed', 'true');
- }
- },
- }),
-);
-
-app.set('view engine', 'ejs');
-app.set('views', 'src/views');
-
-app.get('/', async (req: Request, res: Response) => {
- const browsingTopics = req.get('Sec-Browsing-Topics');
- res.json({topics: browsingTopics});
-});
-
-async function getAdServerAd() {
- const adServerBids = await Promise.all(
- [`${SSP_A_URI}/ad-server-bid`, `${SSP_B_URI}/ad-server-bid`].map(
- async (dspUrl) => {
- const response = await fetch(dspUrl);
- const result = await response.json();
- return result;
- },
- ),
- );
-
- const [highestBid] = adServerBids.sort(
- (a, b) => b.adServerAd.bid - a.adServerAd.bid,
- );
- return highestBid.adServerAd;
-}
-
-app.get('/ad-server-bid', async (req: Request, res: Response) => {
- res.json({
- adServerAd: await getAdServerAd(),
- });
-});
-
-app.get('/reporting', (req, res) => {
- res.send(200);
-});
-
-app.listen(PORT, async () => {
- console.log(`Listening on port ${PORT}`);
-});
diff --git a/services/ad-server/src/public/ad-frame.html b/services/ad-server/src/public/ad-frame.html
deleted file mode 100644
index b825624c..00000000
--- a/services/ad-server/src/public/ad-frame.html
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
-
-
- Container frame
-
-
-
-
-
diff --git a/services/ad-server/src/public/css/global.tailwind.css b/services/ad-server/src/public/css/global.tailwind.css
deleted file mode 100644
index 4c4d1363..00000000
--- a/services/ad-server/src/public/css/global.tailwind.css
+++ /dev/null
@@ -1,7 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-a {
- @apply text-blue-700 underline;
-}
diff --git a/services/ad-server/src/public/js/ad-server-lib.js b/services/ad-server/src/public/js/ad-server-lib.js
deleted file mode 100644
index 2ca534fb..00000000
--- a/services/ad-server/src/public/js/ad-server-lib.js
+++ /dev/null
@@ -1,207 +0,0 @@
-class AdServerLib {
- constructor(hostname) {
- this.adServerOrigin = `https://${hostname}`;
- this.auctions = {};
- }
-
- // The ad server auction runs after the header bidding auction
- async startAdServerAuction({auctionId, headerBiddingAuctionResult}) {
- const adServerAuctionResult = await this.getAdServerAuctionResult();
- const componentAuctionConfigs = headerBiddingAuctionResult.map(
- ({componentAuctionConfig}) => componentAuctionConfig,
- );
-
- return {
- auctionId,
- componentAuctionConfigs,
- contextualAd: this.chooseWinningAd(
- adServerAuctionResult,
- headerBiddingAuctionResult,
- ),
- };
- }
-
- // Fetch the ad server auction bids from the ad server
- async getAdServerAuctionResult() {
- const response = await fetch(`${this.adServerOrigin}/ad-server-bid`);
- const result = await response.json();
-
- return result;
- }
-
- // The ad with a higher bid is chosen between the winner of the header
- // bidding auction and the winner of the ad server auction
- chooseWinningAd(adServerAuctionResult, headerBiddingAuctionResult) {
- const [highestHeaderBid] = headerBiddingAuctionResult.sort(
- (a, b) => b.headerBiddingAd.bid - a.headerBiddingAd.bid,
- );
-
- const {headerBiddingAd} = highestHeaderBid;
- const {adServerAd} = adServerAuctionResult;
-
- return headerBiddingAd.bid > adServerAd.bid ? headerBiddingAd : adServerAd;
- }
-
- // Protected Audience auction is executed after both the header bidding auction
- // and the ad server auction (contextual auction) have concluded
- startProtectedAudienceAuction({auctionId, adUnit, contextualAuctionResult}) {
- const {type: adType, isFencedFrame: resolveToConfig} = adUnit;
- const {contextualAd, componentAuctionConfigs} = contextualAuctionResult;
-
- // The contextual auction ad's bid acts as the bid floor
- const {bid: bidFloor} = contextualAd;
-
- // For the publisher and seller to pass data to component auction sellers
- // and buyers, we add the data to the component auction configs
- const componentAuctions = this.addSignalsToComponentAuctionConfigs({
- componentAuctionConfigs,
- auctionSignals: {adType, auctionId},
- sellerSignals: {'seller-key': 'seller-value'},
- perBuyerSignals: {'buyer-key': 'buyer-value'},
- });
-
- const auctionConfig = {
- // In this demo, the ad server acts as the top-level seller
- seller: this.adServerOrigin,
- decisionLogicURL: `${this.adServerOrigin}/js/decision-logic.js`,
- trustedScoringSignalsURL: `${this.adServerOrigin}/signals/trusted.json`,
- directFromSellerSignalsURL: `${this.adServerOrigin}/signals/direct.json`,
- sellerSignals: {
- bidFloor,
- adType,
- },
- resolveToConfig,
- componentAuctions,
- };
-
- // Adds an iframe that matches the top-level seller origin.
- const containerFrameEl = this.addContainerFrame(adUnit);
-
- // Setup a message listener for VAST XML
- if (adType === 'video') {
- const buyers = this.getBuyers(componentAuctions);
- this.setupVideoAd(buyers);
- }
-
- // The data needed to run a Protected Audience auction is post-messaged to the iframe
- containerFrameEl.addEventListener('load', () => {
- containerFrameEl.contentWindow.postMessage(
- JSON.stringify({auctionId, adUnit, auctionConfig, contextualAd}),
- '*',
- );
- });
- }
-
- getBuyers(componentAuctions) {
- return Array.from(
- new Set(
- ...componentAuctions.map(
- ({interestGroupBuyers}) => interestGroupBuyers,
- ),
- ),
- );
- }
-
- setupVideoAd(buyers) {
- // Listens to the VAST XML from the creative iframe
- window.addEventListener('message', ({origin, data}) => {
- if (buyers.some((buyer) => buyer.includes(origin))) {
- // Pass the VAST XML to the video ad helper that renders the ad
- setUpIMA(data, 'multi');
- }
- });
- }
-
- addSignalsToComponentAuctionConfigs({
- componentAuctionConfigs,
- auctionSignals,
- sellerSignals,
- perBuyerSignals,
- }) {
- this.addComponentAuctionSignals(componentAuctionConfigs, auctionSignals);
- this.addComponentSellerSignals(componentAuctionConfigs, sellerSignals);
- this.addComponentPerBuyerSignals(componentAuctionConfigs, perBuyerSignals);
-
- return componentAuctionConfigs;
- }
-
- // Data from the publisher and the top-level seller are added as
- // auction signals of the component auctions to pass signals to the
- // component buyers and sellers
- addComponentAuctionSignals(componentAuctionConfigs, signals) {
- componentAuctionConfigs = componentAuctionConfigs.map(
- (componentAuctionConfig) => {
- componentAuctionConfig.auctionSignals = {
- ...componentAuctionConfig.auctionSignals,
- ...signals,
- };
-
- return componentAuctionConfig;
- },
- );
- }
-
- // Data from the publisher and the top-level seller are added as
- // seller signals of the component auctions to pass signals to the
- // component sellers
- addComponentSellerSignals(componentAuctionConfigs, signals) {
- componentAuctionConfigs = componentAuctionConfigs.map(
- (componentAuctionConfig) => {
- componentAuctionConfig.sellerSignals = {
- ...componentAuctionConfig.sellerSignals,
- ...signals,
- };
-
- return componentAuctionConfig;
- },
- );
- }
-
- // Data from the publisher and the top-level seller are added as
- // seller signals of the component auctions to pass signals to the
- // component buyers
- addComponentPerBuyerSignals(componentAuctionConfigs, signals) {
- componentAuctionConfigs = componentAuctionConfigs.map(
- (componentAuctionConfig) => {
- componentAuctionConfig.perBuyerSignals = Object.keys(
- componentAuctionConfig.perBuyerSignals,
- ).reduce((updatedPerBuyerSignals, buyerOrigin) => {
- updatedPerBuyerSignals[buyerOrigin] = {
- ...componentAuctionConfig.perBuyerSignals[buyerOrigin],
- ...signals,
- };
-
- return updatedPerBuyerSignals;
- }, {});
-
- return componentAuctionConfig;
- },
- );
- }
-
- addContainerFrame({divId, size, type, isFencedFrame}) {
- const topLevelOrigin = encodeURI(window.location.origin);
- const containerFrameEl = document.createElement('iframe');
- containerFrameEl.src = `${this.adServerOrigin}/ad-frame.html?topLevelOrigin=${topLevelOrigin}`;
-
- // Add a label
- const paragraphEl = document.createElement('p');
- paragraphEl.innerText = `${type} ad in ${
- isFencedFrame ? 'fenced frame' : 'iframe'
- }`.toUpperCase();
- paragraphEl.className = 'font-mono text-sm';
- document.getElementById(divId).appendChild(paragraphEl);
-
- if (type === 'image') {
- [containerFrameEl.width, containerFrameEl.height] = size;
- } else if (type === 'video') {
- // The video creative does not actually render anything, and it only contains
- // the code that post messages the vAST out of the iframe, so we hide it
- containerFrameEl.width = 0;
- containerFrameEl.height = 0;
- }
-
- document.getElementById(divId).appendChild(containerFrameEl);
- return containerFrameEl;
- }
-}
diff --git a/services/ad-server/src/public/js/decision-logic.js b/services/ad-server/src/public/js/decision-logic.js
deleted file mode 100644
index 061080ae..00000000
--- a/services/ad-server/src/public/js/decision-logic.js
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- Copyright 2022 Google LLC
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-function scoreAd(
- adMetadata,
- bid,
- auctionConfig,
- trustedScoringSignals,
- browserSignals,
-) {
- let desirability;
-
- // If it's a video ad, there is no contextual video auction in this demo to compare
- // the bid against, so we just return the desirability score as the bid itself,
- // and the highest bid will win the auction
- if (auctionConfig.sellerSignals.adType === 'video') {
- desirability = bid;
- } else {
- // For an image ad, we compare the PA auction bid against the bid floor set by the
- // winner of the contextual auction (header bidding + ad server auctions)
- // If the contexual auction bid is higher, then we return 0 to filter out this ad
- const {bidFloor} = auctionConfig.sellerSignals;
- desirability = bid > bidFloor ? bid : 0;
- }
-
- return {
- desirability,
- allowComponentAuction: true,
- };
-}
-
-function reportResult(auctionConfig, browserSignals) {
- sendReportTo(auctionConfig.seller + '/reporting?report=result');
- return {
- success: true,
- signalsForWinner: {signalForWinner: 1},
- reportUrl: auctionConfig.seller + '/reporting',
- };
-}
diff --git a/services/ad-server/src/public/js/main.js b/services/ad-server/src/public/js/main.js
deleted file mode 100644
index 9377ce09..00000000
--- a/services/ad-server/src/public/js/main.js
+++ /dev/null
@@ -1,17 +0,0 @@
-'use strict';
-/*
- Copyright 2022 Google LLC
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-console.log('main.js');
diff --git a/services/ad-server/src/public/signals/direct.json b/services/ad-server/src/public/signals/direct.json
deleted file mode 100644
index afec7ce1..00000000
--- a/services/ad-server/src/public/signals/direct.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "direct-key": "direct-value"
-}
diff --git a/services/ad-server/src/public/signals/trusted.json b/services/ad-server/src/public/signals/trusted.json
deleted file mode 100644
index bddc2db2..00000000
--- a/services/ad-server/src/public/signals/trusted.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "trusted-key": "trusted-value"
-}
diff --git a/services/ad-server/tailwind.config.cjs b/services/ad-server/tailwind.config.cjs
deleted file mode 100644
index 0a68d7a5..00000000
--- a/services/ad-server/tailwind.config.cjs
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- Copyright 2022 Google LLC
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- https://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-/** @type {import('tailwindcss').Config} */
-module.exports = {
- content: ['./src/views/*.ejs'],
- theme: {
- extend: {
- fontFamily: {
- serif: [
- 'Cambria',
- 'Cochin',
- 'Georgia',
- 'Times',
- 'Times New Roman',
- 'serif',
- ],
- },
- },
- },
- plugins: [],
-};
diff --git a/services/ad-server/tsconfig.json b/services/ad-server/tsconfig.json
deleted file mode 100644
index c7ad80bc..00000000
--- a/services/ad-server/tsconfig.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "compilerOptions": {
- "target": "es2022",
- "module": "ES2022",
- "rootDir": "./src",
- "esModuleInterop": true,
- "forceConsistentCasingInFileNames": true,
- "strict": true,
- "skipLibCheck": true
- }
-}
diff --git a/services/ad-server/.dockerignore b/services/ad-tech/.dockerignore
similarity index 100%
rename from services/ad-server/.dockerignore
rename to services/ad-tech/.dockerignore
diff --git a/services/dsp-a/.prettierignore b/services/ad-tech/.prettierignore
similarity index 100%
rename from services/dsp-a/.prettierignore
rename to services/ad-tech/.prettierignore
diff --git a/services/ad-server/Dockerfile b/services/ad-tech/Dockerfile
similarity index 100%
rename from services/ad-server/Dockerfile
rename to services/ad-tech/Dockerfile
diff --git a/services/dsp/package-lock.json b/services/ad-tech/package-lock.json
similarity index 62%
rename from services/dsp/package-lock.json
rename to services/ad-tech/package-lock.json
index 6fd7c495..6c6b1fde 100644
--- a/services/dsp/package-lock.json
+++ b/services/ad-tech/package-lock.json
@@ -10,11 +10,15 @@
"license": "apache-2.0",
"dependencies": {
"cbor": "^9.0.2",
+ "cors": "^2.8.5",
"ejs": "^3.1.9",
"express": "^4.18.2",
+ "node-cache": "^5.1.2",
"structured-field-values": "^2.0.1"
},
"devDependencies": {
+ "@types/cors": "^2.8.17",
+ "@types/ejs": "^3.1.5",
"@types/express": "^4.17.17",
"@types/node": "^20.4.2",
"prettier": "^3.0.0",
@@ -27,6 +31,7 @@
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
@@ -35,78 +40,104 @@
}
},
"node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
- "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.14",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
- "dev": true
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@tsconfig/node10": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
- "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
- "dev": true
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
+ "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@tsconfig/node16": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
- "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
- "dev": true
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/body-parser": {
- "version": "1.19.2",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
- "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
+ "version": "1.19.5",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
+ "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/connect": "*",
"@types/node": "*"
}
},
"node_modules/@types/connect": {
- "version": "3.4.35",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
- "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
+ "node_modules/@types/cors": {
+ "version": "2.8.17",
+ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz",
+ "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/ejs": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz",
+ "integrity": "sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/express": {
- "version": "4.17.17",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz",
- "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==",
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
+ "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.33",
@@ -115,54 +146,84 @@
}
},
"node_modules/@types/express-serve-static-core": {
- "version": "4.17.33",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz",
- "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==",
+ "version": "4.19.6",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz",
+ "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/node": "*",
"@types/qs": "*",
- "@types/range-parser": "*"
+ "@types/range-parser": "*",
+ "@types/send": "*"
}
},
+ "node_modules/@types/http-errors": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
+ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/mime": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
- "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==",
- "dev": true
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/node": {
- "version": "20.4.2",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz",
- "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==",
- "dev": true
+ "version": "20.16.10",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
+ "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~6.19.2"
+ }
},
"node_modules/@types/qs": {
- "version": "6.9.7",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
- "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
- "dev": true
+ "version": "6.9.16",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz",
+ "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/range-parser": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
- "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
- "dev": true
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/@types/serve-static": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz",
- "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==",
+ "node_modules/@types/send": {
+ "version": "0.17.4",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
+ "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/mime": "*",
+ "@types/mime": "^1",
"@types/node": "*"
}
},
+ "node_modules/@types/serve-static": {
+ "version": "1.15.7",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
+ "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "*"
+ }
+ },
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "license": "MIT",
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
@@ -172,10 +233,11 @@
}
},
"node_modules/acorn": {
- "version": "8.8.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
- "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "version": "8.12.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz",
+ "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==",
"dev": true,
+ "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -184,10 +246,14 @@
}
},
"node_modules/acorn-walk": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
- "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
"engines": {
"node": ">=0.4.0"
}
@@ -196,6 +262,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -210,38 +277,43 @@
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "license": "MIT"
},
"node_modules/async": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
- "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "license": "MIT"
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
},
"node_modules/body-parser": {
- "version": "1.20.1",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
- "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
+ "version": "1.20.3",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz",
+ "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+ "license": "MIT",
"dependencies": {
"bytes": "3.1.2",
- "content-type": "~1.0.4",
+ "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.1",
+ "qs": "6.13.0",
+ "raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
@@ -254,6 +326,7 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -263,17 +336,25 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "license": "MIT",
"dependencies": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -283,6 +364,7 @@
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz",
"integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==",
+ "license": "MIT",
"dependencies": {
"nofilter": "^3.1.0"
},
@@ -294,6 +376,7 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -305,10 +388,20 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/clone": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -319,17 +412,20 @@
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "license": "MIT"
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "license": "MIT",
"dependencies": {
"safe-buffer": "5.2.1"
},
@@ -341,14 +437,16 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
- "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -356,26 +454,60 @@
"node_modules/cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "license": "MIT"
+ },
+ "node_modules/cors": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
+ "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -384,6 +516,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
@@ -394,6 +527,7 @@
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
@@ -401,12 +535,14 @@
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
},
"node_modules/ejs": {
- "version": "3.1.9",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz",
- "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==",
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
+ "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
+ "license": "Apache-2.0",
"dependencies": {
"jake": "^10.8.5"
},
@@ -418,57 +554,82 @@
}
},
"node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express": {
- "version": "4.18.2",
- "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
- "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
+ "version": "4.21.0",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.21.0.tgz",
+ "integrity": "sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==",
+ "license": "MIT",
"dependencies": {
"accepts": "~1.3.8",
"array-flatten": "1.1.1",
- "body-parser": "1.20.1",
+ "body-parser": "1.20.3",
"content-disposition": "0.5.4",
"content-type": "~1.0.4",
- "cookie": "0.5.0",
+ "cookie": "0.6.0",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "2.0.0",
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
- "finalhandler": "1.2.0",
+ "finalhandler": "1.3.1",
"fresh": "0.5.2",
"http-errors": "2.0.0",
- "merge-descriptors": "1.0.1",
+ "merge-descriptors": "1.0.3",
"methods": "~1.1.2",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
+ "path-to-regexp": "0.1.10",
"proxy-addr": "~2.0.7",
- "qs": "6.11.0",
+ "qs": "6.13.0",
"range-parser": "~1.2.1",
"safe-buffer": "5.2.1",
- "send": "0.18.0",
- "serve-static": "1.15.0",
+ "send": "0.19.0",
+ "serve-static": "1.16.2",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"type-is": "~1.6.18",
@@ -483,6 +644,7 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
"integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "license": "Apache-2.0",
"dependencies": {
"minimatch": "^5.0.1"
}
@@ -491,6 +653,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
@@ -499,6 +662,7 @@
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
@@ -507,12 +671,13 @@
}
},
"node_modules/finalhandler": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
- "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz",
+ "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==",
+ "license": "MIT",
"dependencies": {
"debug": "2.6.9",
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"on-finished": "2.4.1",
"parseurl": "~1.3.3",
@@ -527,6 +692,7 @@
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -535,51 +701,89 @@
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
"node_modules/get-intrinsic": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
- "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "license": "MIT",
"dependencies": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "license": "MIT",
"dependencies": {
- "function-bind": "^1.1.1"
+ "get-intrinsic": "^1.1.3"
},
- "engines": {
- "node": ">= 0.4.0"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-symbols": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -587,10 +791,23 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+ "license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
@@ -606,6 +823,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -616,25 +834,28 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/jake": {
- "version": "10.8.5",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz",
- "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==",
+ "version": "10.9.2",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
+ "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
+ "license": "Apache-2.0",
"dependencies": {
"async": "^3.2.3",
"chalk": "^4.0.2",
- "filelist": "^1.0.1",
- "minimatch": "^3.0.4"
+ "filelist": "^1.0.4",
+ "minimatch": "^3.1.2"
},
"bin": {
"jake": "bin/cli.js"
@@ -647,25 +868,32 @@
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -674,6 +902,7 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "license": "MIT",
"bin": {
"mime": "cli.js"
},
@@ -685,6 +914,7 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -693,6 +923,7 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
@@ -704,6 +935,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -714,28 +946,56 @@
"node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
},
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
+ "node_modules/node-cache": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
+ "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
+ "license": "MIT",
+ "dependencies": {
+ "clone": "2.x"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
"node_modules/nofilter": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz",
"integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==",
+ "license": "MIT",
"engines": {
"node": ">=12.19"
}
},
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
+ "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -744,6 +1004,7 @@
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
@@ -755,20 +1016,23 @@
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
+ "version": "0.1.10",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
+ "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
+ "license": "MIT"
},
"node_modules/prettier": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
- "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
+ "license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
@@ -783,6 +1047,7 @@
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
@@ -792,11 +1057,12 @@
}
},
"node_modules/qs": {
- "version": "6.11.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
- "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
+ "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+ "license": "BSD-3-Clause",
"dependencies": {
- "side-channel": "^1.0.4"
+ "side-channel": "^1.0.6"
},
"engines": {
"node": ">=0.6"
@@ -809,14 +1075,16 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/raw-body": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
- "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
+ "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+ "license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
@@ -844,17 +1112,20 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "MIT"
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
},
"node_modules/send": {
- "version": "0.18.0",
- "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
- "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+ "version": "0.19.0",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz",
+ "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+ "license": "MIT",
"dependencies": {
"debug": "2.6.9",
"depd": "2.0.0",
@@ -874,38 +1145,72 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/send/node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
"node_modules/serve-static": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
- "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
+ "version": "1.16.2",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
+ "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==",
+ "license": "MIT",
"dependencies": {
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
- "send": "0.18.0"
+ "send": "0.19.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
},
"node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -915,19 +1220,22 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/structured-field-values": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/structured-field-values/-/structured-field-values-2.0.1.tgz",
- "integrity": "sha512-1VNk582THEQbA6X7pZF+0mjTH8jD1lvckzZx5gzUW3F6m0Bqi5EJ/WnM4S0egNz+KdKII7A8ArRCqMafZWh7pQ=="
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/structured-field-values/-/structured-field-values-2.0.4.tgz",
+ "integrity": "sha512-5zpJXYLPwW3WYUD/D58tQjIBs10l3Yx64jZfcKGs/RH79E2t9Xm/b9+ydwdMNVSksnsIY+HR/2IlQmgo0AcTAg==",
+ "license": "MIT"
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -939,15 +1247,17 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
"engines": {
"node": ">=0.6"
}
},
"node_modules/ts-node": {
- "version": "10.9.1",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
- "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
+ "version": "10.9.2",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
+ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -990,6 +1300,7 @@
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
@@ -999,10 +1310,11 @@
}
},
"node_modules/typescript": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
- "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
+ "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
"dev": true,
+ "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -1011,10 +1323,18 @@
"node": ">=14.17"
}
},
+ "node_modules/undici-types": {
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -1023,6 +1343,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "license": "MIT",
"engines": {
"node": ">= 0.4.0"
}
@@ -1031,12 +1352,14 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -1046,6 +1369,7 @@
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
diff --git a/services/ad-tech/package.json b/services/ad-tech/package.json
new file mode 100644
index 00000000..f33e7453
--- /dev/null
+++ b/services/ad-tech/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "server",
+ "version": "0.0.0",
+ "license": "apache-2.0",
+ "main": "main.js",
+ "type": "module",
+ "scripts": {
+ "start": "npm run attestation && npm run build && node ./build/main.js",
+ "build": "tsc && cp -r src/views build/",
+ "ncu": "npx npm-check-updates -u",
+ "fmt": "pre-commit run --all-files",
+ "attestation": "if [[ -z \"$npm_config_service\" || -z \"$npm_config_project_env\" ]]; then echo \"Warning: npm_config_service and npm_config_project_env not set. Skipping attestation file copy.\"; else cp -f src/public/.well-known/privacy-sandbox-attestations.json.\"$npm_config_service\".\"$npm_config_project_env\" src/public/.well-known/privacy-sandbox-attestations.json; fi"
+ },
+ "dependencies": {
+ "cbor": "^9.0.2",
+ "cors": "^2.8.5",
+ "ejs": "^3.1.9",
+ "express": "^4.18.2",
+ "node-cache": "^5.1.2",
+ "structured-field-values": "^2.0.1"
+ },
+ "devDependencies": {
+ "@types/cors": "^2.8.17",
+ "@types/ejs": "^3.1.5",
+ "@types/express": "^4.17.17",
+ "@types/node": "^20.4.2",
+ "prettier": "^3.0.0",
+ "ts-node": "^10.9.1",
+ "typescript": "^5.1.6"
+ }
+}
diff --git a/services/ad-tech/src/controllers/key-value-store.ts b/services/ad-tech/src/controllers/key-value-store.ts
new file mode 100644
index 00000000..21099ad1
--- /dev/null
+++ b/services/ad-tech/src/controllers/key-value-store.ts
@@ -0,0 +1,70 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/** BYOS Implementation of K/V Server. */
+export class KeyValueStore {
+ /** In-memory key value store. */
+ private readonly keyValueStore = new Map();
+
+ /** Initial data to rewrite periodically. */
+ private readonly defaultData: string[][];
+
+ /**
+ * @param defaultValues The default values to insert into the store.
+ * @param resetIntervalInMins Interval to reset the store to default values.
+ */
+ constructor(
+ defaultValues: string[][] = [],
+ resetIntervalInMins: number = 30,
+ ) {
+ console.log('Initializing in-memory key value store.', {defaultValues});
+ this.defaultData = defaultValues;
+ this.rewriteDefaults();
+ setInterval(this.rewriteDefaults, 1000 * 60 * resetIntervalInMins);
+ }
+
+ /** Rewrites the default data in the store. */
+ rewriteDefaults = () => {
+ console.log('Resetting real-time signals.');
+ for (const [key, value] of this.defaultData) {
+ if (key) {
+ this.keyValueStore.set(key, value || '');
+ }
+ }
+ };
+
+ /** Set wrapper with value checking. */
+ set = (key: string, value?: string) => {
+ if (value) {
+ console.log('Adding new real-time signal.', {key, value});
+ this.keyValueStore.set(key, value);
+ }
+ };
+
+ /** Returns multiple keys queried from Protected Audience. */
+ getMultiple = (keys: string[]): {[index: string]: string} => {
+ if (!keys) {
+ return {};
+ }
+ const signals: {[index: string]: string} = {};
+ for (const key of keys) {
+ if (key && this.keyValueStore.has(key)) {
+ const value = this.keyValueStore.get(key);
+ if (value) {
+ signals[key] = value;
+ }
+ }
+ }
+ return signals;
+ };
+}
diff --git a/services/ad-tech/src/controllers/report-store.ts b/services/ad-tech/src/controllers/report-store.ts
new file mode 100644
index 00000000..af096803
--- /dev/null
+++ b/services/ad-tech/src/controllers/report-store.ts
@@ -0,0 +1,62 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import NodeCache from 'node-cache';
+
+/** Basic categories of reports. */
+export enum ReportCategory {
+ EVENT_LEVEL_LOG,
+ ARA_EVENT_LEVEL,
+ ARA_EVENT_LEVEL_DEBUG,
+ ARA_AGGREGATE,
+ ARA_AGGREGATE_DEBUG,
+ PAGG_VIA_SS,
+ PAGG_VIA_SS_DEBUG,
+ PAGG_VIA_PAAPI,
+ PAGG_VIA_PAAPI_DEBUG,
+}
+
+/** High-level abstraction of a report. */
+export interface Report {
+ category: ReportCategory;
+ timestamp: string;
+ data: any;
+}
+
+/** TTL for in-memory reports: 10 minutes */
+export const REPORT_TTL_SECONDS = 10 * 60;
+
+/** Simple in-memory implementation of report storage. */
+export const ReportStore = (() => {
+ // In-memory storage for reports.
+ const Reports = new NodeCache({stdTTL: REPORT_TTL_SECONDS});
+
+ /** Add a new report to the in-memory storage. */
+ const addReport = (report: Report) => {
+ // TODO: Consider partitioning by use-case.
+ Reports.set(`${report.category}||${report.timestamp}`, report);
+ };
+
+ /** Returns all reports from in-memory storage. */
+ const getAllReports = (): Report[] => {
+ return Reports.keys().map((key) => Reports.get(key) as Report);
+ };
+
+ return {
+ addReport,
+ getAllReports,
+ };
+})();
diff --git a/services/dsp-a/src/arapi.ts b/services/ad-tech/src/lib/arapi.ts
similarity index 90%
rename from services/dsp-a/src/arapi.ts
rename to services/ad-tech/src/lib/arapi.ts
index 0aec0aba..690ba81e 100644
--- a/services/dsp-a/src/arapi.ts
+++ b/services/ad-tech/src/lib/arapi.ts
@@ -1,3 +1,4 @@
+// FIXME: This file needs to be rationalized with attribution-reporting-helper.ts
/*
Copyright 2022 Google LLC
@@ -14,20 +15,23 @@
limitations under the License.
*/
+import {NEWS_HOST, SHOP_HOST, TRAVEL_HOST} from '../lib/constants.js';
+
// type: 2bit
-const SOURCE_TYPE: {click: number; view: number} = {
+const SOURCE_TYPE: {[index: string]: number} = {
+ unknown: 0b00,
click: 0b10,
view: 0b11,
};
// advertiser: 16bit
const ADVERTISER: {[index: string]: number} = {};
-ADVERTISER[process.env.SHOP_HOST as string] = 0b0;
-ADVERTISER[process.env.TRAVEL_HOST as string] = 0b1;
+ADVERTISER[SHOP_HOST as string] = 0b0;
+ADVERTISER[TRAVEL_HOST as string] = 0b1;
// publisher: 16bit
const PUBLISHER: {[index: string]: number} = {};
-PUBLISHER[process.env.NEWS_HOST as string] = 0b0;
+PUBLISHER[NEWS_HOST as string] = 0b0;
// dimension: 8bit
const DIMENSION: {quantity: number; gross: number} = {
@@ -52,7 +56,7 @@ type AggregationKeyStructure = {
};
export function sourceKeyPiece(ako: AggregationKeyStructure) {
- console.log(ako);
+ console.log('[arapi] sourceKeyPiece: ', ako);
const source = encodeSource(ako);
const uint64: bigint = new DataView(source).getBigUint64(0, false);
return `0x${(uint64 << 64n).toString(16)}`;
@@ -67,7 +71,7 @@ type AggregatableTriggerData = {
};
export function triggerKeyPiece(atd: AggregatableTriggerData) {
- console.log(atd);
+ console.log('[arapi] triggerKeyPiece: ', atd);
const trigger = encodeTrigger(atd);
const uint64 = new DataView(trigger).getBigUint64(0, false);
return `0x${'0'.repeat(16)}${uint64.toString(16)}`;
@@ -159,12 +163,12 @@ export function decodeBucket(buffer: ArrayBuffer) {
export function sourceEventId() {
// 64bit dummy value
- return ((1n << 64n) - 1n).toString();
+ return Math.random().toString().substring(2).replace(/^0/, '');
}
export function debugKey(): string {
// 64bit dummy value
- return ((1n << 64n) - 2n).toString();
+ return Math.random().toString().substring(2).replace(/^0/, '');
}
function key_from_value(object: any, value: any) {
@@ -223,4 +227,4 @@ function test() {
console.log(decodeTrigger(trigger));
}
-test();
+// test();
diff --git a/services/ad-tech/src/lib/attribution-reporting-helper.ts b/services/ad-tech/src/lib/attribution-reporting-helper.ts
new file mode 100644
index 00000000..3988b442
--- /dev/null
+++ b/services/ad-tech/src/lib/attribution-reporting-helper.ts
@@ -0,0 +1,133 @@
+// FIXME: This file needs to be rationalized with arapi.ts
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import {Dictionary} from 'structured-field-values';
+
+import {
+ debugKey,
+ sourceEventId,
+ sourceKeyPiece,
+ triggerKeyPiece,
+ ADVERTISER,
+ PUBLISHER,
+ DIMENSION,
+ SOURCE_TYPE,
+ TRIGGER_TYPE,
+} from './arapi.js';
+import {EXTERNAL_PORT, NEWS_HOST} from './constants.js';
+
+/** Returns a redirect URL for ARA if indicated in query context. */
+export const getAttributionRedirectUrl = (requestQuery: {
+ [key: string]: string;
+}): string | undefined => {
+ if ('redirect' in requestQuery) {
+ // Retain original query params except 'redirect'.
+ const query = Object.entries(requestQuery)
+ .filter(([key, _]) => key !== 'redirect')
+ .map(([key, value]) => `${key}=${value}`)
+ .join('&');
+ const redirectUrl = `${requestQuery['redirect']}/attribution/register-source?${query}`;
+ console.log('[ARA] Following redirect chain: ', redirectUrl);
+ return redirectUrl;
+ }
+};
+
+/** Returns ARA trigger registration headers for the request context. */
+export const getAttributionTriggerHeaders = (requestQuery: {
+ [key: string]: string;
+}): {[key: string]: any} => {
+ return {
+ event_trigger_data: [
+ {
+ trigger_data: '1',
+ priority: '100',
+ // deduplication_key: '1234',
+ },
+ ],
+ aggregatable_trigger_data: [
+ {
+ key_piece: triggerKeyPiece({
+ type: TRIGGER_TYPE['quantity'],
+ id: parseInt(requestQuery.itemId, 16),
+ size: Number(requestQuery.size),
+ category: Number(requestQuery.category),
+ option: 0,
+ }),
+ source_keys: ['quantity'],
+ },
+ {
+ key_piece: triggerKeyPiece({
+ type: TRIGGER_TYPE['gross'],
+ id: parseInt(requestQuery.itemId, 16),
+ size: Number(requestQuery.size),
+ category: Number(requestQuery.category),
+ option: 0,
+ }),
+ source_keys: ['gross'],
+ },
+ ],
+ aggregatable_values: {
+ quantity: Number(requestQuery.quantity),
+ gross: Number(requestQuery.gross),
+ },
+ debug_key: debugKey(),
+ };
+};
+
+/** Returns ARA source registration headers for the request context. */
+export const getAttributionSourceHeaders = (
+ requestQuery: {
+ [key: string]: string;
+ },
+ attributionEligibleHeader: Dictionary,
+): {[key: string]: any} | undefined => {
+ let sourceType = SOURCE_TYPE.unknown;
+ if ('navigation-source' in attributionEligibleHeader) {
+ sourceType = SOURCE_TYPE.click;
+ } else if ('event-source' in attributionEligibleHeader) {
+ sourceType = SOURCE_TYPE.view;
+ } else {
+ console.log(
+ '[ARA] Request header is malformed: ',
+ attributionEligibleHeader,
+ );
+ return;
+ }
+ const {advertiser, itemId} = requestQuery;
+ const destination = `https://${advertiser}:${EXTERNAL_PORT}`;
+ const source_event_id = sourceEventId();
+ const debug_key = debugKey();
+ return {
+ destination,
+ source_event_id,
+ debug_key,
+ debug_reporting: true, // Enable verbose debug reports.
+ aggregation_keys: {
+ quantity: sourceKeyPiece({
+ type: sourceType,
+ advertiser: ADVERTISER[advertiser],
+ publisher: PUBLISHER[NEWS_HOST!],
+ id: Number(`0x${itemId}`),
+ dimension: DIMENSION['quantity'],
+ }),
+ gross: sourceKeyPiece({
+ type: sourceType,
+ advertiser: ADVERTISER[advertiser],
+ publisher: PUBLISHER[NEWS_HOST!],
+ id: Number(`0x${itemId}`),
+ dimension: DIMENSION['gross'],
+ }),
+ },
+ };
+};
diff --git a/services/ad-tech/src/lib/auction-config-helper.ts b/services/ad-tech/src/lib/auction-config-helper.ts
new file mode 100644
index 00000000..9a592c65
--- /dev/null
+++ b/services/ad-tech/src/lib/auction-config-helper.ts
@@ -0,0 +1,87 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import {
+ BUYER_HOSTS_TO_INTEGRATE_BY_SELLER_HOST,
+ CURRENT_ORIGIN,
+ EXTERNAL_PORT,
+ HOSTNAME,
+} from './constants.js';
+
+/** Assembles and returns an auction configuration. */
+export const constructAuctionConfig = (context: {
+ useCase?: string;
+ isFencedFrame?: string;
+ auctionSignals?: {[key: string]: string};
+ sellerSignals?: {[key: string]: any};
+ perBuyerSignals?: {[key: string]: {[key: string]: string}};
+}) => {
+ const interestGroupBuyers = BUYER_HOSTS_TO_INTEGRATE_BY_SELLER_HOST.get(
+ HOSTNAME!,
+ )!.map((buyerHost) => {
+ return new URL(`https://${buyerHost}:${EXTERNAL_PORT}`).toString();
+ });
+ const useCase = context.useCase || 'default';
+ const {isFencedFrame, auctionSignals, sellerSignals, perBuyerSignals} =
+ context;
+ const resolveToConfig = 'true' === isFencedFrame ? true : false;
+ console.log('Constructing auction config', {
+ useCase,
+ isFencedFrame,
+ auctionSignals,
+ sellerSignals,
+ perBuyerSignals,
+ resolveToConfig,
+ });
+ const auctionConfig = {
+ seller: CURRENT_ORIGIN,
+ decisionLogicURL: new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/js/ssp/${useCase}/auction-decision-logic.js`,
+ ).toString(),
+ trustedScoringSignalsURL: new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/ssp/realtime-signals/scoring-signal.json`,
+ ).toString(),
+ /*
+ * TODO: Consider implementing direct from seller signals.
+ * directFromSellerSignals: new URL(
+ * `https://${HOSTNAME}:${EXTERNAL_PORT}/ssp/direct-signal.json`,
+ * ),
+ */
+ interestGroupBuyers,
+ auctionSignals: {
+ 'auction_signals': 'auction_signals',
+ isFencedFrame,
+ ...auctionSignals, // Copy signals from request query.
+ },
+ sellerSignals: {
+ 'seller_signals': 'seller_signals',
+ ...sellerSignals,
+ },
+ perBuyerSignals,
+ // Needed for ad size macro replacements.
+ requestedSize: {'width': '300px', 'height': '250px'},
+ sellerCurrency: 'USD',
+ resolveToConfig,
+ deprecatedRenderURLReplacements: {
+ // This is for the video ads use-case where the DSP is expected to have
+ // included the SSP_VAST macro in the render URL.
+ '${SSP_VAST}': new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/ssp/vast.xml`,
+ ).toString(),
+ '%%SSP_VAST%%': new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/ssp/vast.xml`,
+ ).toString(),
+ },
+ };
+ return auctionConfig;
+};
diff --git a/services/ad-tech/src/lib/common-utils.ts b/services/ad-tech/src/lib/common-utils.ts
new file mode 100644
index 00000000..b3ffded7
--- /dev/null
+++ b/services/ad-tech/src/lib/common-utils.ts
@@ -0,0 +1,117 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import {
+ ADVERTISER_CONTEXTUAL,
+ EXTERNAL_PORT,
+ HOSTNAME,
+ PORT,
+ NEWS_HOST,
+ SHOP_HOST,
+ TRAVEL_HOST,
+ PUBLISHER_IDS,
+} from './constants.js';
+
+/** Returns template variables for the contextual advertiser. */
+export const getContextualAdTemplateVariables = () => {
+ const registerSourceUrl = new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/attribution/register-source`,
+ );
+ registerSourceUrl.searchParams.append('advertiser', ADVERTISER_CONTEXTUAL);
+ return {
+ TITLE: `Contextual ads from ${ADVERTISER_CONTEXTUAL}`,
+ DESTINATION: new URL(`https://${TRAVEL_HOST}:${EXTERNAL_PORT}`).toString(),
+ CREATIVE: new URL( // Doughnut image.
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/img/emoji_u1f369.svg`,
+ ).toString(),
+ ATTRIBUTION_SRC: registerSourceUrl.toString(),
+ };
+};
+
+/** Returns variables for use in the ad template for Protected Audience. */
+export const getInterestGroupAdTemplateVariables = (requestQuery: any) => {
+ const advertiser = requestQuery.advertiser?.toString() || HOSTNAME!;
+ const destination = new URL(`https://${advertiser}:${EXTERNAL_PORT}`);
+ const creative = new URL(`https://${advertiser}:${EXTERNAL_PORT}`);
+ const registerSourceUrl = new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/attribution/register-source`,
+ );
+ registerSourceUrl.searchParams.append('advertiser', advertiser);
+ const itemId = requestQuery.itemId?.toString() || '';
+ if (itemId) {
+ // Load specific ad for SHOP advertiser.
+ destination.pathname = `/items/${itemId}`;
+ creative.pathname = `/ads/${itemId}`;
+ registerSourceUrl.searchParams.append('itemId', itemId);
+ } else {
+ if (HOSTNAME === advertiser) {
+ // If advertiser is current ad-tech itself, show static ad.
+ creative.pathname = '/img/emoji_u1f4b0.svg'; // Bag of cash image.
+ } else {
+ creative.pathname = '/ads';
+ }
+ }
+ return {
+ TITLE: `Your special ads from ${advertiser}`,
+ DESTINATION: destination,
+ CREATIVE: creative,
+ ATTRIBUTION_SRC: registerSourceUrl.toString(),
+ };
+};
+
+/** Returns variables for use in the MTA template. */
+export const getStaticAdTemplateVariables = (
+ requestQuery: any,
+ requestHeaders: any,
+) => {
+ const getPublisherId = (requestHeaders: any) => {
+ const refererUrl = new URL(
+ requestHeaders.referer || `https://${NEWS_HOST}/`,
+ );
+ return PUBLISHER_IDS[refererUrl.hostname] || '9999';
+ };
+
+ const itemId = requestQuery.itemId?.toString() || '1f45f';
+
+ return {
+ TITLE: `Your special ads from ${SHOP_HOST}`,
+ DESTINATION: new URL(
+ `https://${SHOP_HOST}:${EXTERNAL_PORT}/items/${itemId}`,
+ ),
+ CREATIVE: new URL(`https://${SHOP_HOST}:${EXTERNAL_PORT}/ads/${itemId}`),
+ PUBLISHER_ID: getPublisherId(requestHeaders),
+ CAMPAIGN_ID: 1234,
+ };
+};
+
+/** Returns EJS template variables for EJS files. */
+export const getTemplateVariables = (titleMessage: string = '') => {
+ const hostDetails = {
+ HOSTNAME,
+ EXTERNAL_PORT,
+ PORT,
+ SHOP_HOST,
+ TITLE: `${HOSTNAME} - ${titleMessage}`,
+ };
+ console.log('Built template context: ', hostDetails);
+ return hostDetails;
+};
+
+/** Returns the given argument as a structured stringified object. */
+export const getStructuredObject = (obj: any): {[key: string]: string} => {
+ const params: {[key: string]: string} = {};
+ for (const [key, value] of Object.entries(obj)) {
+ params[key] = value as string;
+ }
+ return params;
+};
diff --git a/services/ad-tech/src/lib/constants.ts b/services/ad-tech/src/lib/constants.ts
new file mode 100644
index 00000000..534b23f3
--- /dev/null
+++ b/services/ad-tech/src/lib/constants.ts
@@ -0,0 +1,207 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// ****************************************************************************
+// ENVIRONMENT VARIABLES
+// ****************************************************************************
+export const {
+ // Runtime variables
+ PORT,
+ EXTERNAL_PORT,
+ HOSTNAME,
+ DEMO_HOST_PREFIX,
+
+ // Advertisers
+ SHOP_HOST,
+ SHOP_DETAIL,
+ TRAVEL_HOST,
+ TRAVEL_DETAIL,
+
+ // Publishers
+ NEWS_HOST,
+ NEWS_DETAIL,
+ MOTO_NEWS_HOST,
+ SOCCER_NEWS_HOST,
+ GARDENING_NEWS_HOST,
+
+ // Ad-techs
+ DSP_HOST,
+ DSP_DETAIL,
+ DSP_URI,
+
+ DSP_A_HOST,
+ DSP_A_DETAIL,
+ DSP_A_URI,
+
+ DSP_B_HOST,
+ DSP_B_DETAIL,
+ DSP_B_URI,
+
+ SSP_HOST,
+ SSP_DETAIL,
+ SSP_URI,
+
+ SSP_A_HOST,
+ SSP_A_DETAIL,
+ SSP_A_URI,
+
+ SSP_B_HOST,
+ SSP_B_DETAIL,
+ SSP_B_URI,
+
+ AD_SERVER_HOST,
+ AD_SERVER_DETAIL,
+ AD_SERVER_URI,
+} = process.env;
+
+export const CURRENT_ORIGIN = new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}`,
+).toString();
+
+// ****************************************************************************
+// BIDDING SIGNALS - CONTEXTUAL AUCTIONS
+// ****************************************************************************
+// NOTE: These bidding signals are only used on the server-side to respond to a
+// contextual bid request from the browser or server-to-server.
+/**
+ * Name of the contextual advertiser.
+ * This is used in the buyer's bid response to contextual bid requests.
+ */
+export const ADVERTISER_CONTEXTUAL = 'ContextNext';
+/** Max bid CPM for contextual auctions. */
+export const CONTEXTUAL_BID_MAX = 1.5;
+/** Min bid CPM for contextual auctions. */
+export const CONTEXTUAL_BID_MIN = 0.5;
+
+// ****************************************************************************
+// BIDDING SIGNALS - PROTECTED AUDIENCE AUCTIONS
+// ****************************************************************************
+// NOTE: These bidding signals are stored in the BYOS Key-Value Server, where
+// values are stored as strings.
+/** The deafult bidding signals for the BYOS Key-Value Serice. */
+export const BIDDING_SIGNALS_DEFAULT = [
+ // Whether the campaign is active.
+ ['isActive', 'true'],
+ // Min bid CPM for Protected Audience auctions.
+ ['minBid', '3.5'],
+ // Max bid CPM for Protected Audience auctions.
+ ['maxBid', '4.5'],
+ // Default bid multiplier for Protected Audience auctions.
+ ['multiplier', '1.1'],
+];
+/** Deal specific bid multipliers for Protected Audience auctions. */
+export const BIDDING_SIGNALS_DEALS = [
+ // Template for keys: `multiplier-${dealId}`
+ ['multiplier-deal-1', '0.5'], // Deal ID: deal-1
+ ['multiplier-deal-2', '0.4'], // Deal ID: deal-2
+ ['multiplier-deal-3', '0.45'], // Deal ID: deal-3
+];
+
+// ****************************************************************************
+// ADVERTISER METADATA
+// ****************************************************************************
+/**
+ * Map of SHOP advertiser's item metadata. Map contains item tags indexed by
+ * itemId.
+ * This is currently used to initialize the sellers's BYOS key-value store for
+ * the Protected Audience seller's realtime creative scoring signals use-case.
+ */
+export const KNOWN_SHOP_ITEM_TAGS_BY_ID = {
+ '1f45e': ['brownShoe'], // Brown leather shoe
+ '1f45f': ['blueShoe', 'sportsShoe'], // Blue running shoe
+ '1f460': ['redShoe'], // Red high-heeled shoe
+ '1f461': ['brownShoe'], // Heeled backless sandal
+ '1f462': ['brownShoe'], // Brown boot
+ '1f6fc': ['blueShoe', 'sportsShoe'], // Roller skate
+ '1f97e': ['brownShoe', 'sportsShoe'], // Hiking boot
+ '1f97f': ['blueShoe'], // Blue flat shoe
+ '1fa70': ['brownShoe'], // Ballet shoes
+ '1fa74': ['blueShoe'], // Thong sandal
+ '1f3bf': ['blueShoe', 'sportsShoe'], // Ski boots
+ '26f8': ['sportsShoe'], // Ice skates
+};
+
+// ****************************************************************************
+// PROTECTED AUDIENCE RENDER URL MACROS
+// ****************************************************************************
+/**
+ * This macro is used with render URLs for display ads, where AD_WIDTH and
+ * AD_HEIGHT are natively supported macros in Protected Audience. These macros
+ * may be specified in either formats: ${...} or {%...%}
+ *
+ * For the macro replacement to work, the SSP needs to request an ad size in
+ * the auction configuration and the DSP needs to specify the ad size with the
+ * bid. The values returned by the DSP are used for macro replacements. These
+ * values need not match the size requested by the SSP. Regardless of whether
+ * the ad size included in the DSP's bid matches the ad size requested by the
+ * SSP, the decision is made via the SSP's scoring logic. Both the requested
+ * and the response ad sizes are accessible the SSP's scoreAd().
+ */
+export const MACRO_DISPLAY_RENDER_URL_AD_SIZE =
+ 'adSize1={%AD_WIDTH%}x{%AD_HEIGHT%}&adSize2=${AD_WIDTH}x${AD_HEIGHT}';
+
+/**
+ * This macro is used in render URLs for video ads, where SSP_VAST is a custom
+ * macro included in the SSP's component auction configuration. At render time,
+ * this macro will be replaced with the winning SSP's VAST XML endpoint. This
+ * SSP endpoint returns a wrapped VAST XML for a given DSP VAST XML and
+ * auction ID.
+ */
+export const MACRO_VIDEO_RENDER_URL_SSP_VAST =
+ 'sspVast=${SSP_VAST}&sspVastAlt=%%SSP_VAST%%';
+
+// ****************************************************************************
+// INTEGRATION CONFIGURATIONS
+// ****************************************************************************
+/**
+ * Map of buyers to integrate with indexed by sellers.
+ * This is meant to showcase business relationships between buyers and sellers.
+ * When a buyer is integrated with the seller, the seller sends contextual bid
+ * requests to the buyer and includes the buyer as an interest group buyer in
+ * its Protected Audience component auction config.
+ */
+export const BUYER_HOSTS_TO_INTEGRATE_BY_SELLER_HOST = new Map([
+ // ad-server -> dsp + dsp-a + dsp-b
+ [AD_SERVER_HOST!, [DSP_HOST!, DSP_A_HOST!, DSP_B_HOST!]],
+ // ssp -> dsp-a + dsp-b
+ [SSP_HOST!, [DSP_A_HOST!, DSP_B_HOST!]],
+ // ssp-a -> dsp + dsp-a
+ [SSP_A_HOST!, [DSP_HOST!, DSP_A_HOST!]],
+ // ssp-b -> dsp + dsp-b
+ [SSP_B_HOST!, [DSP_HOST!, DSP_B_HOST!]],
+]);
+
+// ****************************************************************************
+// INTEGRATION CONFIGURATIONS
+// ****************************************************************************
+/** Variables referenced in static JavaScript template files. */
+export const JAVASCRIPT_TEMPLATE_VARIABLES = {
+ DEMO_HOST_PREFIX,
+ AD_SERVER_HOST,
+ ADVERTISER_CONTEXTUAL,
+ HOSTNAME,
+};
+
+// ****************************************************************************
+// PUBLISHER METADATA
+// ****************************************************************************
+/**
+ * List of publishers and their IDs for any use case that needs to identify
+ * the publisher
+ */
+export const PUBLISHER_IDS: {[hostname: string]: string} = {
+ [NEWS_HOST!]: '1000',
+ [MOTO_NEWS_HOST!]: '2000',
+ [SOCCER_NEWS_HOST!]: '3000',
+ [GARDENING_NEWS_HOST!]: '4000',
+};
diff --git a/services/ad-tech/src/lib/contextual-auction-helper.ts b/services/ad-tech/src/lib/contextual-auction-helper.ts
new file mode 100644
index 00000000..dfef3293
--- /dev/null
+++ b/services/ad-tech/src/lib/contextual-auction-helper.ts
@@ -0,0 +1,146 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+import {
+ DSP_A_HOST,
+ DSP_A_URI,
+ DSP_B_HOST,
+ DSP_B_URI,
+ DSP_HOST,
+ DSP_URI,
+} from './constants.js';
+
+/**
+ * Generalized contents of a contextual bid response.
+ * Where a contextual bid request / response references everything that is not
+ * originating from Protected Audience. This interface is shared between the
+ * contextual bid responses from both the buyer and the seller endpoints.
+ */
+export interface ContextualBidResponse {
+ // FIELDS GENERALLY PRESENT ON ALL RESPONSES THAT AREN'T ERRORS:
+ /**
+ * Hostname of the bidder that is responding to the HTTP request, but need
+ * not be the ad buyer placing the bid.
+ */
+ bidderHost?: string;
+ /**
+ * Origin of the bidder that is responding to the HTTP request, but need not
+ * be the ad buyer placing the bid.
+ */
+ bidderOrigin?: string;
+ /** Unique auction ID for the current request / response context. */
+ auctionId?: string;
+ /** Bid CPM in USD with 2 decimal digits. */
+ bid?: string;
+ /** URL of the ad creative. */
+ renderURL?: string;
+
+ // FIELDS THAT ARE ONLY FOUND ON SPECIFIC RESPONSES AS NOTED BELOW
+ /**
+ * Included in buyer's server-to-server response to seller's request.
+ * Buyer signals to include in component auction config. The buyer may choose
+ * to not include additional signals or not participate in the Protected
+ * Audience auction altogether as well.
+ */
+ buyerSignals?: any;
+ /**
+ * Included in seller's response to ad server's request from the browser.
+ * Hostname of the ultimate ad buyer placing the bid while bidderHost is set
+ * to the ad seller responding to the bid request.
+ */
+ buyerHost?: string;
+ /**
+ * Included in seller's response to ad server's request from the browser.
+ * Origin of the ultimate ad buyer placing the bid while bidderHost is set to
+ * the ad seller responding to the bid request.
+ */
+ buyerOrigin?: string;
+ /**
+ * Included in seller's response to ad server's request from the browser.
+ * Component auction configuration to include in the overall Protected
+ * Audience auction configuration.
+ */
+ componentAuctionConfig?: any;
+}
+
+/** Timeout of 5 seconds for before the ad seller responds to the request. */
+export const CONTEXTUAL_AUCTION_TIMEOUT_MS = 5000;
+
+/** Returns the contextual bidding URL for a given origin. */
+const getContextualBidUrl = (origin: string) => {
+ const contextualBidUrl = new URL(origin);
+ contextualBidUrl.pathname = '/dsp/contextual-bid';
+ return contextualBidUrl.toString();
+};
+
+/**
+ * We use an environment variable to determine the contextual bidding endpoint
+ * because the origins vary across the execution environments -- local, dev,
+ * and prod deployments. For local deployments, we rely on Docker mesh for
+ * networking, routing requests to: http://...dsp.dev:8080/, while in dev and
+ * prod environments, these need to be plain HTTPS requests made to the public
+ * endpoint: https://...dsp.dev:443/
+ */
+/** Map of ad buyer contextual bidding URLs indexed by hostname. */
+export const CONTEXTUAL_ENDPOINT_BY_BUYER_HOST = new Map([
+ [DSP_HOST!, getContextualBidUrl(DSP_URI!)],
+ [DSP_A_HOST!, getContextualBidUrl(DSP_A_URI!)],
+ [DSP_B_HOST!, getContextualBidUrl(DSP_B_URI!)],
+]);
+
+// ****************************************************************************
+// EXPORTED FUNCTIONS
+// ****************************************************************************
+/**
+ * Executes a contextual auction and returns all the contextual bid responses.
+ * The invoker is assumed to be on the sell-side, with the specified bidders
+ * on the buy-side. As such, the contextual bid requests are made to the
+ * `/dsp/contextual-bid` path.
+ */
+export async function getContextualBids(
+ bidderHosts: string[] = [],
+ signals: {[key: string]: string} = {},
+): Promise {
+ console.log('Starting contextual auction', {bidderHosts, signals});
+ const bidQuery = Object.entries(signals)
+ .map(([key, value]) => `${key}=${value}`)
+ .join('&');
+ const bidUrls = bidderHosts.map((host) => {
+ const contextualEndpoint = CONTEXTUAL_ENDPOINT_BY_BUYER_HOST.get(host);
+ return `${contextualEndpoint}?${bidQuery}`;
+ });
+ const bidResponsePromises = bidUrls.map(async (bidUrl) => {
+ console.log('Making contextual bid request', {bidUrl});
+ const response = await fetch(bidUrl);
+ if (response.ok) {
+ const bidResponse = await response.json();
+ console.log('Received contextual bid response', {bidResponse});
+ return bidResponse;
+ } else {
+ console.log('Error in contextual bid response', {response});
+ return {bid: '0.0'};
+ }
+ });
+ // Use Promise.race to implement a timeout for the contextual auction.
+ const bidResponses = await Promise.race([
+ (await Promise.allSettled(bidResponsePromises))
+ .filter((p) => p.status === 'fulfilled')
+ .map((p) => p.value),
+ new Promise((resolve) =>
+ setTimeout(() => resolve([]), CONTEXTUAL_AUCTION_TIMEOUT_MS),
+ ),
+ ]);
+ return bidResponses;
+}
diff --git a/services/ad-tech/src/lib/interest-group-helper.ts b/services/ad-tech/src/lib/interest-group-helper.ts
new file mode 100644
index 00000000..d2196b1f
--- /dev/null
+++ b/services/ad-tech/src/lib/interest-group-helper.ts
@@ -0,0 +1,255 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import {
+ CURRENT_ORIGIN,
+ BIDDING_SIGNALS_DEFAULT,
+ EXTERNAL_PORT,
+ HOSTNAME,
+ MACRO_DISPLAY_RENDER_URL_AD_SIZE,
+ MACRO_VIDEO_RENDER_URL_SSP_VAST,
+ BIDDING_SIGNALS_DEALS,
+} from './constants.js';
+
+// ****************************************************************************
+// ENUMS AND INTERFACES
+// ****************************************************************************
+/** Supported ad types. */
+export enum AdType {
+ DISPLAY = 'DISPLAY',
+ VIDEO = 'VIDEO',
+}
+
+/** Interface for an interest group ad object. */
+export interface InterestGroupAd {
+ // REQUIRED FIELDS
+ /** Main creative URL. */
+ renderURL: string;
+ /** Custom ad metadata stored by ad-tech. */
+ metadata: {
+ /** Hostname of the advertiser. */
+ advertiser: string;
+ /** DSIPLAY or VIDEO */
+ adType: AdType;
+ /** List of compatible ad sizes. */
+ adSizes?: InterestGroupAdSize[];
+ };
+ // OPTIONAL FIELDS
+ /** Associated ad size group label. */
+ sizeGroup?: string;
+ // [Optional] Reporting IDs
+ /** Selectable reporting ID accessible to both buyer and seller. */
+ selectableBuyerAndSellerReportingIds?: string[];
+ /** Non-selectable reporting ID accessible to buyer only. */
+ buyerReportingId?: string;
+ /** Non-selectable reporting ID accessible to both buyer and seller. */
+ buyerAndSellerReportingId?: string;
+}
+
+/** Generalized interface of an ad size. */
+export interface InterestGroupAdSize {
+ width: string;
+ height: string;
+}
+
+/** Top-level interface of an interest group. */
+export interface InterestGroup {
+ /** Name of the interest group: ${advertiser}-${usecase} */
+ name: string;
+ /** Origin for the ad buyer. */
+ owner: string;
+ /** URL to script defining generateBid() and reportWin(). */
+ biddingLogicURL?: string;
+ /** Endpoint for real-time bidding signals. */
+ trustedBiddingSignalsURL?: string;
+ /** Real-time bidding signals to query for. */
+ trustedBiddingSignalsKeys?: string[];
+ /** Endpoint to periodically update the interest group. */
+ updateURL?: string;
+ /** User-specific bidding signals to consider while bidding. */
+ userBiddingSignals?: {[key: string]: string};
+ /** All ads to consider while bidding. */
+ ads?: InterestGroupAd[];
+ /** Map of ad sizes indexed by a label for the size. */
+ adSizes?: {[key: string]: InterestGroupAdSize};
+ /** Map of ad size labels indexed by the ad size group label. */
+ sizeGroups?: {[key: string]: string[]};
+}
+
+/** Generalized interface of the interest group targeting context. */
+export interface TargetingContext {
+ // REQUIRED FIELDS
+ /** Hostname of the advertiser. */
+ advertiser: string;
+ /** Usecase for targeting, or 'default'. */
+ usecase: string;
+ /** Whether this is a fresh request or an update. */
+ isUpdateRequest: boolean;
+ // OPTIONAL FIELDS
+ /** Advertiser prouct item ID. */
+ itemId?: string;
+ /** Real-time bidding signal keys to include in the interest group. */
+ biddingSignalKeys?: string[];
+ /** All other undocumented custom query parameters. */
+ additionalContext?: {[key: string]: string[]};
+}
+
+// ****************************************************************************
+// HELPER FUNCTIONS
+// ****************************************************************************
+/** Returns video ads for a given advertiser and SSP hosts to integrate. */
+const getVideoAdForRequest = (
+ targetingContext: TargetingContext,
+): InterestGroupAd => {
+ const {advertiser} = targetingContext;
+ const renderUrl = new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/ads/video-ads?`,
+ );
+ renderUrl.searchParams.append('advertiser', advertiser);
+ const ad: InterestGroupAd = {
+ renderURL: `${renderUrl.toString()}&${MACRO_VIDEO_RENDER_URL_SSP_VAST}`,
+ metadata: {
+ advertiser,
+ adType: AdType.VIDEO,
+ },
+ buyerReportingId: 'buyerSpecificInfo1',
+ buyerAndSellerReportingId: 'seatid-1234',
+ };
+ if (targetingContext.isUpdateRequest) {
+ // Only include deal IDs in update requests.
+ ad.selectableBuyerAndSellerReportingIds = ['deal-1', 'deal-2', 'deal-3'];
+ }
+ return ad;
+};
+
+/** Returns the interest group display ad to for the given advertiser. */
+const getDisplayAdForRequest = (
+ targetingContext: TargetingContext,
+): InterestGroupAd => {
+ const {advertiser, itemId} = targetingContext;
+ const renderUrl = new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/ads/display-ads`,
+ );
+ renderUrl.searchParams.append('advertiser', advertiser);
+ if (itemId) {
+ renderUrl.searchParams.append('itemId', itemId);
+ }
+ const ad: InterestGroupAd = {
+ renderURL: `${renderUrl.toString()}&${MACRO_DISPLAY_RENDER_URL_AD_SIZE}`,
+ metadata: {
+ advertiser,
+ adType: AdType.DISPLAY,
+ adSizes: [{width: '300px', height: '250px'}],
+ },
+ sizeGroup: 'medium-rectangle',
+ buyerReportingId: 'buyerSpecificInfo1',
+ buyerAndSellerReportingId: 'seatid-1234',
+ };
+ if (targetingContext.isUpdateRequest) {
+ // Only include deal IDs in update requests.
+ ad.selectableBuyerAndSellerReportingIds = ['deal-1', 'deal-2', 'deal-3'];
+ }
+ return ad;
+};
+
+/** Returns the interest group name to use. */
+const getInterestGroupName = (targetingContext: TargetingContext): string => {
+ const {advertiser, usecase} = targetingContext;
+ return `${advertiser}-${usecase}`;
+};
+
+/** Returns the update URL with the targeting context. */
+const constructInterestGroupUpdateUrl = (
+ targetingContext: TargetingContext,
+): string => {
+ const interestGroupName = getInterestGroupName(targetingContext);
+ const updateURL = new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/dsp/interest-group-update.json`,
+ );
+ updateURL.searchParams.append('interestGroupName', interestGroupName);
+ updateURL.searchParams.append('advertiser', targetingContext.advertiser);
+ updateURL.searchParams.append('usecase', targetingContext.usecase);
+ if (targetingContext.itemId) {
+ updateURL.searchParams.append('itemId', targetingContext.itemId);
+ }
+ if (targetingContext.biddingSignalKeys?.length) {
+ updateURL.searchParams.append(
+ 'biddingSignalKeys',
+ targetingContext.biddingSignalKeys.join(','),
+ );
+ }
+ if (targetingContext.additionalContext) {
+ for (const [key, value] of Object.entries(
+ targetingContext.additionalContext,
+ )) {
+ updateURL.searchParams.append(key, value.join(','));
+ }
+ }
+ return updateURL.toString();
+};
+
+/** Returns the bidding signal keys to include in the interest group. */
+const getBiddingSignalKeys = (targetingContext: TargetingContext): string[] => {
+ const biddingSignalsKeys = [...BIDDING_SIGNALS_DEFAULT.map(([key]) => key)];
+ if (targetingContext.biddingSignalKeys) {
+ biddingSignalsKeys.push(...targetingContext.biddingSignalKeys);
+ }
+ if (targetingContext.isUpdateRequest) {
+ // Only include keys related to deals for update requests.
+ biddingSignalsKeys.push(...BIDDING_SIGNALS_DEALS.map(([key]) => key));
+ }
+ return biddingSignalsKeys;
+};
+
+// ****************************************************************************
+// EXPORTED FUNCTIONS
+// ****************************************************************************
+/** Returns the interest group for the given targeting context. */
+export const getInterestGroup = (
+ targetingContext: TargetingContext,
+): InterestGroup => {
+ const {usecase} = targetingContext;
+ const userBiddingSignals: {[key: string]: string} = {
+ 'user-signal-key-1': 'user-signal-value-1',
+ };
+ if (targetingContext.additionalContext) {
+ for (const [key, values] of Object.entries(
+ targetingContext.additionalContext,
+ )) {
+ userBiddingSignals[key] = JSON.stringify(values);
+ }
+ }
+ return {
+ name: getInterestGroupName(targetingContext),
+ owner: CURRENT_ORIGIN,
+ biddingLogicURL: new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/js/dsp/${usecase}/auction-bidding-logic.js`,
+ ).toString(),
+ trustedBiddingSignalsURL: new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/dsp/realtime-signals/bidding-signal.json`,
+ ).toString(),
+ trustedBiddingSignalsKeys: getBiddingSignalKeys(targetingContext),
+ updateURL: constructInterestGroupUpdateUrl(targetingContext),
+ userBiddingSignals,
+ ads: [
+ getDisplayAdForRequest(targetingContext),
+ getVideoAdForRequest(targetingContext),
+ ],
+ adSizes: {
+ 'medium-rectangle-default': {'width': '300px', 'height': '250px'},
+ },
+ sizeGroups: {
+ 'medium-rectangle': ['medium-rectangle-default'],
+ },
+ };
+};
diff --git a/services/ad-tech/src/main.ts b/services/ad-tech/src/main.ts
new file mode 100644
index 00000000..e5f617cc
--- /dev/null
+++ b/services/ad-tech/src/main.ts
@@ -0,0 +1,61 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Application} from 'express';
+import cors from 'cors';
+
+import {HOSTNAME, PORT} from './lib/constants.js';
+import {BiddingSignalsRouter} from './routes/dsp/bidding-signals-router.js';
+import {BuyerContextualBidderRouter} from './routes/dsp/buyer-contextual-bidder-router.js';
+import {BuyerRouter} from './routes/dsp/buyer-router.js';
+import {CommonRouter} from './routes/common/common-router.js';
+import {ScoringSignalsRouter} from './routes/ssp/scoring-signals-router.js';
+import {SellerContextualBidderRouter} from './routes/ssp/seller-contextual-bidder-router.js';
+import {SellerRouter} from './routes/ssp/seller-router.js';
+import {WellKnownAttributionReportingRouter} from './routes/well-known/well-known-attribution-reporting-router.js';
+import {WellKnownPrivateAggregationRouter} from './routes/well-known/well-known-private-aggregation-router.js';
+import {AdsRouter} from './routes/common/ads-router.js';
+import {ReportRouter} from './routes/common/report-router.js';
+import {AttributionReportingRouter} from './routes/common/attribution-reporting-router.js';
+import {TopicsRouter} from './routes/common/topics-router.js';
+
+const app: Application = express();
+app.use(express.urlencoded({extended: true}));
+app.use(express.json());
+app.use(cors());
+app.set('view engine', 'ejs');
+app.set('views', 'src/views');
+
+app.use('/', CommonRouter);
+app.use('/ads', AdsRouter);
+app.use('/reporting', ReportRouter);
+app.use('/attribution', AttributionReportingRouter);
+app.use('/topics', TopicsRouter);
+
+app.use(
+ '/.well-known/attribution-reporting',
+ WellKnownAttributionReportingRouter,
+);
+app.use('/.well-known/private-aggregation', WellKnownPrivateAggregationRouter);
+
+app.use('/dsp', BuyerRouter);
+app.use('/dsp/contextual-bid', BuyerContextualBidderRouter);
+app.use('/dsp/realtime-signals', BiddingSignalsRouter);
+
+app.use('/ssp', SellerRouter);
+app.use('/ssp/contextual-bid', SellerContextualBidderRouter);
+app.use('/ssp/realtime-signals', ScoringSignalsRouter);
+
+app.listen(PORT, function () {
+ console.log(HOSTNAME, ' listening on port ', PORT);
+});
diff --git a/services/ad-server/src/public/.well-known/privacy-sandbox-attestations.json b/services/ad-tech/src/public/.well-known/privacy-sandbox-attestations.json
similarity index 100%
rename from services/ad-server/src/public/.well-known/privacy-sandbox-attestations.json
rename to services/ad-tech/src/public/.well-known/privacy-sandbox-attestations.json
diff --git a/services/dsp-a/src/public/css/index.css b/services/ad-tech/src/public/css/index.css
similarity index 100%
rename from services/dsp-a/src/public/css/index.css
rename to services/ad-tech/src/public/css/index.css
diff --git a/services/ad-tech/src/public/img/emoji_u1f369.svg b/services/ad-tech/src/public/img/emoji_u1f369.svg
new file mode 100644
index 00000000..9a973277
--- /dev/null
+++ b/services/ad-tech/src/public/img/emoji_u1f369.svg
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/ad-tech/src/public/img/emoji_u1f4b0.svg b/services/ad-tech/src/public/img/emoji_u1f4b0.svg
new file mode 100644
index 00000000..0d281d87
--- /dev/null
+++ b/services/ad-tech/src/public/img/emoji_u1f4b0.svg
@@ -0,0 +1,265 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/ad-server/src/public/img/spy.svg b/services/ad-tech/src/public/img/spy.svg
similarity index 100%
rename from services/ad-server/src/public/img/spy.svg
rename to services/ad-tech/src/public/img/spy.svg
diff --git a/services/ad-tech/src/public/js/contextual-ad-frame.js b/services/ad-tech/src/public/js/contextual-ad-frame.js
new file mode 100644
index 00000000..9c575cb1
--- /dev/null
+++ b/services/ad-tech/src/public/js/contextual-ad-frame.js
@@ -0,0 +1,35 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This script is included on the ad frame hosted by this ad-tech, and is
+ * executed when an ad is delivered by this ad-tech on a publisher page.
+ *
+ * What does this script do:
+ * This script does nothing functionally. It only adds a descriptive label
+ * about the ad buyer to the ad frame.
+ */
+(() => {
+ // Adds a descriptive label to the ad for demonstrative purposes.
+ const currentUrl = new URL(location.href);
+ const advertiser = currentUrl.searchParams.get('advertiser') || '';
+ const host = new URL(document.currentScript.src).hostname;
+ document.addEventListener('DOMContentLoaded', async () => {
+ const $adLabel = document.getElementById('ad-label');
+ const advertiserSuffix = advertiser ? ` for ${advertiser}` : '';
+ if ($adLabel) {
+ $adLabel.innerText = `Contextual ad from ${host}${advertiserSuffix}`;
+ }
+ });
+})();
diff --git a/services/ad-tech/src/public/js/display-ad-frame.js b/services/ad-tech/src/public/js/display-ad-frame.js
new file mode 100644
index 00000000..a3b558cc
--- /dev/null
+++ b/services/ad-tech/src/public/js/display-ad-frame.js
@@ -0,0 +1,63 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This script is included in Protected Audience display ads, and is executed
+ * when an ad is delivered by this ad-tech on a publisher page.
+ *
+ * What does this script do:
+ * This script triggers the ad beacon that the ad-tech expects to have
+ * pre-registered in the Protected Audience reporting phase using
+ * registerAdBeacon().
+ */
+(() => {
+ /** Triggers all the ad beacons registered in Protected Audience auction. */
+ const triggerAdBeacons = () => {
+ if (!window.fence?.reportEvent) {
+ console.log('[PSDemo] Fenced frames ads reporting API not available.');
+ return;
+ }
+ window.fence.reportEvent({
+ 'eventType': 'impression',
+ 'destination': ['buyer', 'seller', 'component-seller'],
+ });
+ window.fence.setReportEventDataForAutomaticBeacons({
+ 'eventType': 'reserved.top_navigation_start',
+ 'eventData': '{"event": "top_navigation_start"}',
+ 'destination': ['seller', 'buyer', 'component-seller'],
+ });
+ window.fence.setReportEventDataForAutomaticBeacons({
+ 'eventType': 'reserved.top_navigation_commit',
+ 'eventData': '{"event": "top_navigation_commit"}',
+ 'destination': ['seller', 'buyer', 'component-seller'],
+ });
+ };
+
+ /** Adds a description for demonstrative purposes. */
+ const addDescriptionToAdContainer = () => {
+ const host = new URL(document.currentScript.src).hostname;
+ document.addEventListener('DOMContentLoaded', async (e) => {
+ const $adLabel = document.getElementById('ad-label');
+ if ($adLabel) {
+ $adLabel.innerText = `PAAPI ad from ${host}`;
+ }
+ });
+ };
+
+ /** Main function */
+ (() => {
+ addDescriptionToAdContainer();
+ triggerAdBeacons();
+ })();
+})();
diff --git a/services/ad-tech/src/public/js/dsp/default/auction-bidding-logic.js b/services/ad-tech/src/public/js/dsp/default/auction-bidding-logic.js
new file mode 100644
index 00000000..aa24e794
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/default/auction-bidding-logic.js
@@ -0,0 +1,318 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This is the 'default' auction bidding logic for a DSP.
+ *
+ * What does this script do?
+ * This script is used by interest groups to generate bids and report on
+ * participation in Protected Audience auctions.
+ */
+
+// ********************************************************
+// Helper Functions
+// ********************************************************
+CURR_HOST = '';
+AUCTION_ID = '';
+/** Logs to console. */
+function log(message, context) {
+ console.log(
+ '[PSDemo] Buyer',
+ CURR_HOST,
+ 'bidding logic',
+ AUCTION_ID,
+ message,
+ JSON.stringify({context}, ' ', ' '),
+ );
+}
+
+/** Logs execution context for demonstrative purposes. */
+function logContextForDemo(message, context) {
+ const {
+ interestGroup,
+ auctionSignals,
+ perBuyerSignals,
+ // UNUSED trustedBiddingSignals,
+ // UNUSED browserSignals,
+ sellerSignals,
+ } = context;
+ AUCTION_ID = auctionSignals.auctionId;
+ if (interestGroup) {
+ CURR_HOST = interestGroup.owner.substring('https://'.length);
+ } else if (perBuyerSignals && perBuyerSignals.buyerHost) {
+ CURR_HOST = perBuyerSignals.buyerHost;
+ } else if (sellerSignals && sellerSignals.buyer) {
+ CURR_HOST = sellerSignals.buyer.substring('https://'.length);
+ }
+ log(message, context);
+}
+
+/** Checks whether the current ad campaign is active. */
+function isCurrentCampaignActive(biddingContext) {
+ const {
+ // UNUSED interestGroup,
+ // UNUSED auctionSignals,
+ // UNUSED perBuyerSignals,
+ trustedBiddingSignals,
+ browserSignals,
+ } = biddingContext;
+ if ('true' !== trustedBiddingSignals['isActive']) {
+ // Don't place a bid if campaign is inactive.
+ log('not bidding since campaign is inactive', {
+ trustedBiddingSignals,
+ seller: browserSignals.seller,
+ topLevelSeller: browserSignals.topLevelSeller,
+ dataVersion: browserSignals.dataVersion,
+ });
+ return false;
+ }
+ return true;
+}
+
+/** Calculates a bid price based on real-time signals. */
+function calculateBidAmount(trustedBiddingSignals, dealId) {
+ const minBid = Number(trustedBiddingSignals.minBid) || 0.5;
+ const maxBid = Number(trustedBiddingSignals.maxBid) || 1.5;
+ let multiplier = 1.0;
+ if (dealId) {
+ // If an eligible deal is found, use the corresponding bid multiplier.
+ multiplier = Number(trustedBiddingSignals[`multiplier-${dealId}`]) || 0.5;
+ } else {
+ multiplier = Number(trustedBiddingSignals.multiplier) || 1.0;
+ }
+ let bid = Math.random() * (maxBid - minBid) + minBid;
+ bid = (bid * multiplier).toFixed(2);
+ log('calculated bid price', {bid, minBid, maxBid, multiplier});
+ return bid;
+}
+
+/** Selects a deal ID from selectable buyer and seller reporting IDs. */
+function selectDealId(selectedAd, auctionSignals) {
+ const {
+ buyerReportingId,
+ buyerAndSellerReportingId,
+ selectableBuyerAndSellerReportingIds,
+ } = selectedAd;
+ if (
+ !selectableBuyerAndSellerReportingIds ||
+ !selectableBuyerAndSellerReportingIds.length
+ ) {
+ // No deal IDs in interest group to choose from.
+ return;
+ }
+ // Filter deals in interest group with deals from bid request.
+ const eligibleDeals = ((dealsQuery) => {
+ const availableDeals = dealsQuery?.split(',');
+ if (availableDeals && availableDeals.length) {
+ return selectableBuyerAndSellerReportingIds.filter((id) =>
+ auctionSignals.availableDeals.includes(id),
+ );
+ }
+ })(auctionSignals.availableDeals);
+ if (!eligibleDeals || !eligibleDeals.length) {
+ // No eligible deals for this bid request.
+ return;
+ }
+ // Choose one of the eligible deals at random.
+ const countOfEligibleIds = eligibleDeals.length;
+ const randomIndex = Math.floor(Math.random() * countOfEligibleIds);
+ const selectedId = eligibleDeals[randomIndex];
+ // Log reporting IDs to console.
+ log('found reporting IDs', {
+ buyerReportingId,
+ buyerAndSellerReportingId,
+ selectableBuyerAndSellerReportingIds,
+ selectedId,
+ });
+ return selectedId;
+}
+
+/** Returns the bid response for a video ad request. */
+function getBidForVideoAd({
+ interestGroup,
+ auctionSignals,
+ // UNUSED perBuyerSignals,
+ trustedBiddingSignals,
+ browserSignals,
+}) {
+ const {ads} = interestGroup;
+ // Select an ad meeting the auction requirements.
+ const [selectedAd] = ads.filter((ad) => 'VIDEO' === ad.metadata.adType);
+ if (!selectedAd) {
+ log('didnt find eligible video ad in IG', {interestGroup, browserSignals});
+ return {bid: '0.0'};
+ }
+ // Check if any deals are eligible.
+ const dealId = selectDealId(selectedAd, auctionSignals);
+ return {
+ ad: {
+ ...selectedAd.metadata,
+ seller: browserSignals.seller,
+ topLevelSeller: browserSignals.topLevelSeller,
+ },
+ bid: calculateBidAmount(trustedBiddingSignals, dealId),
+ bidCurrency: 'USD',
+ allowComponentAuction: true,
+ render: selectedAd.renderURL,
+ // Specify selected deal ID for reporting.
+ selectedBuyerAndSellerReportingId: dealId,
+ /*
+ TODO: Use-case: Ad cost reporting
+ adCost: optionalAdCost,
+ */
+ /*
+ TODO: Use-case: Modeling signals
+ modelingSignals: 123,
+ */
+ };
+}
+
+/** Returns the bid response for a display ad request. */
+function getBidForDisplayAd({
+ interestGroup,
+ auctionSignals,
+ // UNUSED perBuyerSignals,
+ trustedBiddingSignals,
+ browserSignals,
+}) {
+ // Select an ad meeting the auction requirements.
+ const [selectedAd] = interestGroup.ads.filter(
+ (ad) => 'DISPLAY' === ad.metadata.adType,
+ );
+ if (!selectedAd) {
+ log("can't select display ad, no matching ad type found", {interestGroup});
+ return {bid: '0.0'};
+ }
+ // Check if any deals are eligible.
+ const dealId = selectDealId(selectedAd, auctionSignals);
+ return {
+ ad: {
+ ...selectedAd.metadata,
+ seller: browserSignals.seller,
+ topLevelSeller: browserSignals.topLevelSeller,
+ },
+ bid: calculateBidAmount(trustedBiddingSignals, dealId),
+ bidCurrency: 'USD',
+ allowComponentAuction: true,
+ render: {
+ url: selectedAd.renderURL,
+ // Specify ad size for macro replacements.
+ width: selectedAd.metadata.adSizes[0].width,
+ height: selectedAd.metadata.adSizes[0].height,
+ },
+ // Specify selected deal ID for reporting.
+ selectedBuyerAndSellerReportingId: dealId,
+ /*
+ TODO: Use-case: Ad cost reporting
+ adCost: optionalAdCost,
+ */
+ /*
+ TODO: Use-case: Ad components
+ adComponents:[
+ {url: adComponent1, width: componentWidth1, height: componentHeight1},
+ {url: adComponent2, width: componentWidth2, height: componentHeight2},
+ ],
+ targetNumAdComponents: 3,
+ numMandatoryAdComponents: 1,
+ */
+ /*
+ TODO: Use-case: Modeling signals
+ modelingSignals: 123,
+ */
+ };
+}
+
+// ********************************************************
+// Top-level Protected Audience functions
+// ********************************************************
+function generateBid(
+ interestGroup,
+ auctionSignals,
+ perBuyerSignals,
+ trustedBiddingSignals,
+ browserSignals,
+) {
+ const biddingContext = {
+ interestGroup,
+ auctionSignals,
+ perBuyerSignals,
+ trustedBiddingSignals,
+ browserSignals,
+ };
+ logContextForDemo('generateBid()', biddingContext);
+ if (!isCurrentCampaignActive(biddingContext)) {
+ log('not bidding as campaign is inactive', biddingContext);
+ return;
+ }
+ const bid =
+ 'VIDEO' === auctionSignals.adType
+ ? getBidForVideoAd(biddingContext)
+ : getBidForDisplayAd(biddingContext);
+ if (bid) {
+ log('returning bid', {bid, biddingContext});
+ return bid;
+ } else {
+ log('not bidding', {biddingContext});
+ }
+}
+
+function reportWin(
+ auctionSignals,
+ perBuyerSignals,
+ sellerSignals,
+ browserSignals,
+) {
+ logContextForDemo('reportWin()', {
+ auctionSignals,
+ perBuyerSignals,
+ sellerSignals,
+ browserSignals,
+ });
+ // Assemble query parameters for event logs.
+ let additionalQueryParams = browserSignals.renderURL.substring(
+ browserSignals.renderURL.indexOf('?') + 1,
+ );
+ const reportingContext = {
+ auctionId: AUCTION_ID,
+ pageURL: auctionSignals.pageURL,
+ componentSeller: browserSignals.seller,
+ topLevelSeller: browserSignals.topLevelSeller,
+ renderURL: browserSignals.renderURL,
+ bid: browserSignals.bid,
+ bidCurrency: browserSignals.bidCurrency,
+ buyerReportingId: browserSignals.buyerReportingId,
+ buyerAndSellerReportingId: browserSignals.buyerAndSellerReportingId,
+ selectedBuyerAndSellerReportingId:
+ browserSignals.selectedBuyerAndSellerReportingId,
+ };
+ for (const [key, value] of Object.entries(reportingContext)) {
+ additionalQueryParams = additionalQueryParams.concat(`&${key}=${value}`);
+ }
+ sendReportTo(
+ browserSignals.interestGroupOwner +
+ `/reporting?report=win&${additionalQueryParams}`,
+ );
+ // Disable redirect chain temporarily to make ARA debugging easier.
+ // additionalQueryParams = additionalQueryParams.concat(
+ // `&redirect=${browserSignals.seller}`,
+ // );
+ registerAdBeacon({
+ 'impression': `${browserSignals.interestGroupOwner}/reporting?report=impression&${additionalQueryParams}`,
+ 'reserved.top_navigation_start': `${browserSignals.interestGroupOwner}/reporting?report=top_navigation_start&${additionalQueryParams}`,
+ 'reserved.top_navigation_commit': `${browserSignals.interestGroupOwner}/reporting?report=top_navigation_commit&${additionalQueryParams}`,
+ });
+}
diff --git a/services/ad-tech/src/public/js/dsp/dsp-tag.js b/services/ad-tech/src/public/js/dsp/dsp-tag.js
new file mode 100644
index 00000000..5e089fa3
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/dsp-tag.js
@@ -0,0 +1,119 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This is the only script that is included on the advertiser's page, and is
+ * responsible for orchestrating other ad-tech modules as needed.
+ *
+ * What does this script do:
+ * This is the main tag for an ad buyer or a Demand Side Platform - DSP. This
+ * script loads additional iframes from its own origin for various use-cases.
+ * This script contains a few helper functions that help copy over
+ * first-party context attached either to the top-level page URL or to the
+ * current script tag.
+ */
+
+(async () => {
+ // ********************************************************
+ // HELPER FUNCTIONS
+ // ********************************************************
+ /** Injects an iframe using the current script's reference. */
+ const injectIframe = (src, options) => {
+ if (!src) {
+ return;
+ }
+ const $iframe = document.createElement('iframe');
+ $iframe.src = src;
+ $iframe.width = 1;
+ $iframe.height = 1;
+ $iframe.async = true;
+ $iframe.defer = true;
+ if (options && 'object' === typeof options) {
+ for (const [key, value] of Object.entries(options)) {
+ $iframe.setAttribute(key, value);
+ }
+ }
+ console.log('[PSDemo] Ad buyer injecting iframe', {src, $iframe});
+ const $script = document.currentScript;
+ $script.parentElement.insertBefore($iframe, $script);
+ };
+
+ /** Returns additional page context data to be captured. */
+ const getPageContextData = () => {
+ const pageContext = {
+ title: document.title,
+ isMobile: navigator.userAgentData.mobile,
+ platform: navigator.userAgentData.platform,
+ };
+ return pageContext;
+ };
+
+ /** Copies first-party context onto iframe URL. */
+ const getServerUrlWithPageContext = (pathname) => {
+ if (!pathname) {
+ return;
+ }
+ // Construct iframe URL using current script origin.
+ const $script = document.currentScript;
+ const src = new URL($script.src);
+ src.pathname = pathname;
+ // Append query parameters from script dataset context.
+ for (const datakey in $script.dataset) {
+ src.searchParams.append(datakey, $script.dataset[datakey]);
+ }
+ if (!$script.dataset.advertiser) {
+ // Manually attach advertiser if missing.
+ src.searchParams.append('advertiser', location.hostname);
+ }
+ // Append query params from page URL.
+ const currentUrl = new URL(location.href);
+ for (const [key, value] of currentUrl.searchParams) {
+ src.searchParams.append(key, value);
+ }
+ // Append additional page context data.
+ for (const [key, value] of Object.entries(getPageContextData())) {
+ src.searchParams.append(key, value);
+ }
+ return src;
+ };
+
+ // ********************************************************
+ // MAIN FUNCTION
+ // ********************************************************
+ (() => {
+ /** Inject DSP iframe to execute scripts in ad-tech's origin context.
+ */
+ injectIframe(
+ /* src= */ getServerUrlWithPageContext(
+ /* pathname= */ 'dsp/dsp-advertiser-iframe.html',
+ ),
+ /* options= */ {
+ allow: 'join-ad-interest-group',
+ browsingTopics: '',
+ },
+ );
+
+ /** Additional iframes to be injected go here... */
+
+ /** Test only */
+ if (false) {
+ // Private Aggregation test
+ injectIframe(
+ /* src= */ getServerUrlWithPageContext(
+ /* pathname= */ 'dsp/test-private-aggregation.html',
+ ),
+ );
+ }
+ })();
+})();
diff --git a/services/ad-tech/src/public/js/dsp/join-ad-interest-group.js b/services/ad-tech/src/public/js/dsp/join-ad-interest-group.js
new file mode 100644
index 00000000..f34cd455
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/join-ad-interest-group.js
@@ -0,0 +1,62 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This script is loaded in the join-ad-interest-group.html iframe.
+ *
+ * What does this script do:
+ * This script starts by querying the ad-tech server (same origin to current
+ * script) to retrieve interest group metadata to use with the Protected
+ * Audience API on the client-side. First-party context is also included in
+ * this request to the ad-tech server which includes URL query parameters
+ * from the top-level page as well as any script dataset context directly
+ * attached to the DSP tag.
+ */
+
+(() => {
+ /** Sends first-party context to server to retrieve interest group metadata. */
+ getInterestGroupFromServer = async () => {
+ const currentUrl = new URL(location.href);
+ const interestGroupUrl = new URL(location.origin);
+ interestGroupUrl.pathname = '/dsp/interest-group.json';
+ // Copy query params from current context.
+ for (const [key, value] of currentUrl.searchParams) {
+ interestGroupUrl.searchParams.append(key, value);
+ }
+ // TODO: Consider using Topics API for choosing Ads
+ // const topics = await document.browsingTopics?
+ // console.log({ topics })
+ // interestGroupUrl.searchParams.append('topics', topics);
+ const res = await fetch(interestGroupUrl, {browsingTopics: true});
+ if (res.ok) {
+ return res.json();
+ }
+ };
+
+ document.addEventListener('DOMContentLoaded', async () => {
+ if (navigator.joinAdInterestGroup === undefined) {
+ console.log('[PSDemo] Protected Audience API is not supported.');
+ return;
+ }
+ const interestGroup = await getInterestGroupFromServer();
+ console.log('[PSDemo] Joining interest group: ', {interestGroup});
+ const kSecsPerDay = 3600 * 24 * 30;
+ console.log(
+ await navigator.joinAdInterestGroup(interestGroup, kSecsPerDay),
+ );
+ });
+})();
diff --git a/services/ad-tech/src/public/js/dsp/mta-conversion-tag.js b/services/ad-tech/src/public/js/dsp/mta-conversion-tag.js
new file mode 100644
index 00000000..6f13fffa
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/mta-conversion-tag.js
@@ -0,0 +1,17 @@
+(() => {
+ const $script = document.currentScript;
+ const scriptSrc = $script.getAttribute('src');
+ const purchaseValue = $script.getAttribute('purchaseValue');
+ const mtaConversionTagURL = new URL(scriptSrc);
+ mtaConversionTagURL.pathname = '/dsp/mta-conversion.html';
+ mtaConversionTagURL.searchParams.append('purchaseValue', purchaseValue);
+
+ const $iframe = document.createElement('iframe');
+ $iframe.width = 1;
+ $iframe.height = 1;
+ $iframe.src = mtaConversionTagURL;
+ $iframe.setAttribute('scrolling', 'no');
+ $iframe.setAttribute('style', 'border: none');
+
+ $script.parentElement.insertBefore($iframe, $script);
+})();
diff --git a/services/ad-tech/src/public/js/dsp/mta-conversion-worklet.js b/services/ad-tech/src/public/js/dsp/mta-conversion-worklet.js
new file mode 100644
index 00000000..4d6cee90
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/mta-conversion-worklet.js
@@ -0,0 +1,64 @@
+const SCALE_FACTOR = 256;
+
+function generateAggregationKey(campaignId, publisherId) {
+ const aggregationKey = BigInt(`${campaignId}${publisherId}`);
+ return aggregationKey;
+}
+
+class MultiTouchAttributionConversion {
+ async run(data) {
+ const {campaignId, purchaseValue} = data;
+ console.log('Purchase value for MTA Conversion: ' + purchaseValue);
+
+ // Read from Shared Storage
+ const impressionContextSSKey = 'impressionContext' + campaignId;
+ console.log('Reading from Shared Storage. Key: ' + impressionContextSSKey);
+ let impressions = await sharedStorage.get(impressionContextSSKey);
+
+ // Do not report if there isn't any impression
+ if (!impressions) {
+ console.log(
+ "Couldn't find impressions in Shared Storage. Key: " +
+ impressionContextSSKey,
+ );
+ return;
+ }
+
+ // Impressions saved in the Shared Storage will have this format:
+ // "|{"publisherId":"1000","campaignId":"123","timestamp":1723061856804}|{"publisherId":"2000","campaignId":"123","timestamp":1723061876437}|..."
+ // So, we need to split using the delimeter '|' after removing the first character
+
+ impressions = impressions.substring(1);
+ const impressionsArray = impressions.split('|');
+ const numberImpressions = impressionsArray.length;
+
+ console.log('MTA conversion - Found ' + numberImpressions + ' impressions');
+
+ // Custom logic for Multi Touch Attribution
+ // In this example, we are splitting the total purchase value of this campaign equally between all impressions
+ // (which might have duplicate publishers)
+
+ impressionsArray.forEach((impression) => {
+ let impressionParsed = JSON.parse(impression);
+
+ // Generate the aggregation key and the aggregatable value
+ const bucket = generateAggregationKey(
+ campaignId,
+ impressionParsed.publisherId,
+ );
+ const value =
+ Math.floor(purchaseValue / numberImpressions) * SCALE_FACTOR;
+
+ // Send an aggregatable report via the Private Aggregation API
+ console.log('contributeToHistogram ' + bucket + ' ' + value);
+ privateAggregation.contributeToHistogram({bucket, value});
+ });
+
+ // Delete these impressions after the conversion and reporting
+ await sharedStorage.delete(impressionContextSSKey);
+ console.log('Deleted Shared Storage. Key: ' + impressionContextSSKey);
+ }
+}
+
+// Register the operation
+register('mta-conversion', MultiTouchAttributionConversion);
diff --git a/services/ad-tech/src/public/js/dsp/mta-conversion.js b/services/ad-tech/src/public/js/dsp/mta-conversion.js
new file mode 100644
index 00000000..c1c7f09e
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/mta-conversion.js
@@ -0,0 +1,17 @@
+const mtaConversionScript = document.querySelector('#mta-conversion');
+const campaignId = mtaConversionScript.dataset.campaignId;
+const purchaseValue = mtaConversionScript.dataset.purchaseValue;
+
+async function multiTouchAttributionConversion() {
+ // Load the Shared Storage worklet
+ const sharedStorageWorklet = await window.sharedStorage.createWorklet(
+ '/js/dsp/mta-conversion-worklet.js',
+ );
+
+ // Run the multi touch attribution logic
+ await sharedStorageWorklet.run('mta-conversion', {
+ data: {campaignId: campaignId, purchaseValue: purchaseValue},
+ });
+}
+
+multiTouchAttributionConversion();
diff --git a/services/ad-tech/src/public/js/dsp/private-aggregation-worklet.js b/services/ad-tech/src/public/js/dsp/private-aggregation-worklet.js
new file mode 100644
index 00000000..4ac96e1f
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/private-aggregation-worklet.js
@@ -0,0 +1,52 @@
+// FIXME: Refactor this file into a specific use-case.
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * This script needs to be refactored into a specific use-case.
+ *
+ * This is a simple script to test aggregate reporting with Shared Storage and
+ * Private Aggregation. This script is executed inside a Shared Storage
+ * worklet.
+ */
+
+class TestPrivateAggregation {
+ async run(data) {
+ let cloudEnv = await sharedStorage.get('cloudenv');
+ console.log(`Enabling ${cloudEnv} Private Aggregation Debug Mode`);
+ privateAggregation.enableDebugMode({debugKey: 1234n});
+ let bucketKey = await sharedStorage.get('bucket');
+ if (!bucketKey) {
+ console.log(
+ '[PSDemo] No bucket key found for client. ',
+ 'Adding default bucketKey 1234567890.',
+ );
+ bucketKey = '1234567890';
+ sharedStorage.set('bucketKey', bucketKey);
+ } else {
+ console.log('[PSDemo] Bucket Key found: ', {bucketKey});
+ }
+ function convertToBucket(bucketId) {
+ return BigInt(bucketId);
+ }
+ const bucket = convertToBucket(bucketKey);
+ const value = 128;
+ privateAggregation.contributeToHistogram({bucket, value});
+ sharedStorage.clear();
+ }
+}
+
+register('test-private-aggregation', TestPrivateAggregation);
diff --git a/services/ad-tech/src/public/js/dsp/static-ad-tag.js b/services/ad-tech/src/public/js/dsp/static-ad-tag.js
new file mode 100644
index 00000000..442c2b0b
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/static-ad-tag.js
@@ -0,0 +1,15 @@
+(() => {
+ const $script = document.currentScript;
+ const scriptSrc = $script.getAttribute('src');
+ const staticAdURL = new URL(scriptSrc);
+ staticAdURL.pathname = '/ads/static-ads';
+
+ const $iframe = document.createElement('iframe');
+ $iframe.width = 300;
+ $iframe.height = 250;
+ $iframe.src = staticAdURL;
+ $iframe.setAttribute('scrolling', 'no');
+ $iframe.setAttribute('style', 'border: none');
+ $iframe.setAttribute('allow', 'attribution-reporting');
+ $script.parentElement.insertBefore($iframe, $script);
+})();
diff --git a/services/ad-tech/src/public/js/dsp/test-private-aggregation.js b/services/ad-tech/src/public/js/dsp/test-private-aggregation.js
new file mode 100644
index 00000000..73d09bc4
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/test-private-aggregation.js
@@ -0,0 +1,47 @@
+// FIXME: Refactor this file into a specific use-case.
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * This script needs to be refacted into a specific use-case.
+ *
+ * This is a simple script to test aggregate reporting with Shared Storage and
+ * Private Aggregation. This script is loaded inside the
+ * dsp/test-private-aggregation.html iframe, and invokes a Shared Storage
+ * worklet.
+ */
+
+(async () => {
+ let bucket = document.currentScript.getAttribute('bucket');
+ let cloudEnv = document.currentScript.getAttribute('cloudenv');
+
+ sharedStorage.set('bucket', `${bucket}`);
+ sharedStorage.set('cloudenv', `${cloudEnv}`);
+ console.log(
+ `https://publickeyservice.msmt.${cloudEnv}.privacysandboxservices.com`,
+ );
+
+ const privateAggCloud = {
+ 'privateAggregationConfig': {
+ 'aggregationCoordinatorOrigin': `https://publickeyservice.msmt.${cloudEnv}.privacysandboxservices.com`,
+ },
+ };
+
+ await window.sharedStorage.worklet.addModule(
+ '/js/dsp/private-aggregation-worklet.js',
+ );
+ await window.sharedStorage.run('test-private-aggregation', privateAggCloud);
+})();
diff --git a/services/ad-tech/src/public/js/dsp/write-impression-context-to-shared-storage.js b/services/ad-tech/src/public/js/dsp/write-impression-context-to-shared-storage.js
new file mode 100644
index 00000000..642ce897
--- /dev/null
+++ b/services/ad-tech/src/public/js/dsp/write-impression-context-to-shared-storage.js
@@ -0,0 +1,22 @@
+const writeImpressionContextScript = document.querySelector(
+ '#write-impression-context',
+);
+const campaignId = writeImpressionContextScript.dataset.campaignId;
+const publisherId = writeImpressionContextScript.dataset.publisherId;
+
+const impressionContextSSKey = 'impressionContext' + campaignId;
+const impressionContext = {
+ publisherId: publisherId,
+ campaignId: campaignId,
+ timestamp: Date.now(),
+};
+
+const valueToAppend = `|${JSON.stringify(impressionContext)}`;
+window.sharedStorage.append(impressionContextSSKey, valueToAppend);
+console.log(
+ "Appended '" +
+ valueToAppend +
+ "' to SharedStorage key '" +
+ impressionContextSSKey +
+ "'.",
+);
diff --git a/services/ad-tech/src/public/js/ssp/ad-server-tag.js b/services/ad-tech/src/public/js/ssp/ad-server-tag.js
new file mode 100644
index 00000000..ae7b4692
--- /dev/null
+++ b/services/ad-tech/src/public/js/ssp/ad-server-tag.js
@@ -0,0 +1,214 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This is the main tag for an ad seller delivering ads in a single seller
+ * setup. This is included on certain tagged publisher pages.
+ *
+ * What does this script do:
+ * This script orchestrates the loading of other seller modules to deliver
+ * relevant ads for all the ad slots available on the publisher page. This
+ * script reads the ad slot configurations set by the publisher and injects
+ * an iframe for each ad slot. These iframes then individually execute ad
+ * auctions to select the ad as per publisher configurations.
+ */
+(() => {
+ /** Current script domain name. */
+ const CURR_HOSTNAME = new URL(document.currentScript.src).hostname;
+ // ********************************************************
+ // HELPER FUNCTIONS
+ // ********************************************************
+ /** Logs to console. */
+ const log = (message, context) => {
+ console.log('[PSDemo] Seller', CURR_HOSTNAME, 'ad tag', message, {context});
+ };
+
+ /** Returns frame URL with page context as search query. */
+ const getIframeUrlWithPageContext = () => {
+ // Construct iframe URL using current script origin.
+ const $script = document.currentScript;
+ const src = new URL($script.src);
+ src.pathname = '/ssp/run-sequential-ad-auction.html';
+ // Append query parameters from script dataset context.
+ for (const datakey in $script.dataset) {
+ src.searchParams.append(datakey, $script.dataset[datakey]);
+ }
+ // Append query params from page URL.
+ const currentUrl = new URL(location.href);
+ for (const [key, value] of currentUrl.searchParams) {
+ src.searchParams.append(key, value);
+ }
+ src.searchParams.append('publisher', location.origin);
+ src.searchParams.append('title', document.title);
+ return src;
+ };
+
+ /** Injects an iframe using the current script's reference. */
+ const injectAndReturnIframe = ({src, divId, size, attributes}) => {
+ if (!src) {
+ return;
+ }
+ const iframeEl = document.createElement('iframe');
+ iframeEl.src = src;
+ [iframeEl.width, iframeEl.height] = size;
+ if (attributes && 'object' === typeof attributes) {
+ for (const [key, value] of Object.entries(attributes)) {
+ iframeEl.setAttribute(key, value);
+ }
+ }
+ log('injecting iframe', {src, divId, iframeEl});
+ document.getElementById(divId).appendChild(iframeEl);
+ return iframeEl;
+ };
+
+ /** Listen for potential post messages from DSPs. */
+ const addEventListenerForDspPostMessages = () => {
+ window.addEventListener('message', async (event) => {
+ if (!event.origin.startsWith('https://<%= DEMO_HOST_PREFIX %>')) {
+ return;
+ }
+ if ('string' === typeof event.data) {
+ try {
+ const {auctionId, buyer, vastXml} = JSON.parse(event.data);
+ log('received VAST post-message from DSP', {auctionId, buyer, event});
+ if (vastXml) {
+ log('setting up video ad', {auctionId, buyer, vastXml});
+ window.PSDemo.VideoAdHelper.setUpIMA(vastXml);
+ }
+ } catch (err) {
+ log('encountered error while parsing post-message', {e});
+ }
+ }
+ });
+ log('listening for post-messages from buyers');
+ };
+
+ /** Adds a descriptive label for demonstration purposes. */
+ const addDescriptionToAdContainer = (divId, adType, isFencedFrame) => {
+ const paragraphEl = document.createElement('p');
+ paragraphEl.innerText = `${adType} ad in ${
+ isFencedFrame ? 'FENCED FRAME' : 'IFRAME'
+ } by ${CURR_HOSTNAME}`;
+ paragraphEl.className = 'ad-label';
+ const adContainer = document.getElementById(divId);
+ if (adContainer) {
+ adContainer.appendChild(paragraphEl);
+ } else {
+ log('did not find ad container ', {divId, adType});
+ }
+ };
+
+ /** Validates the adUnit configuration. */
+ const isValidAdUnit = (adUnit) => {
+ const {divId, adType, isFencedFrame, size} = adUnit;
+ if (!divId) {
+ log('did not find divId in adUnit', {adUnit});
+ return false;
+ }
+ const $divEl = document.getElementById(divId);
+ if (!$divEl) {
+ log('did not find ad container on page', {adUnit});
+ return false;
+ }
+ if (!adType) {
+ log('did not find adType in adUnit', {adUnit});
+ return false;
+ }
+ if (!['DISPLAY', 'VIDEO'].includes(adType)) {
+ log('found unsupported adType', {adUnit});
+ return false;
+ }
+ if ('VIDEO' === adType && isFencedFrame) {
+ log('does not support video ads in fenced frames', {adUnit});
+ return false;
+ }
+ if (!size || size.length !== 2) {
+ log('expected size to be an array of 2: [w, h] in adUnit', {adUnit});
+ return false;
+ }
+ return true;
+ };
+
+ /** Iterates through adUnit configs and delivers ads. */
+ const deliverAds = (adUnits, otherSellers) => {
+ // Iterate over adUnits and inject an ad-container iframe for each adUnit.
+ // The container iframe has additional scripts to execute ad auctions for
+ // a given adUnit config. This ad-server-tag will post message the adUnit config
+ // to the injected iframe once it's loaded.
+ for (const adUnit of adUnits) {
+ if (!isValidAdUnit(adUnit)) {
+ continue;
+ }
+ log('processing adUnit', {adUnit});
+ const {divId, adType, isFencedFrame} = adUnit;
+ let {size} = adUnit;
+ addDescriptionToAdContainer(divId, adType, isFencedFrame);
+ if ('VIDEO' === adType.toUpperCase()) {
+ addEventListenerForDspPostMessages();
+ size[1] = 48; // Set height to 48px, just enough for a description.
+ }
+ const src = getIframeUrlWithPageContext();
+ log('injecting iframe for adUnit', {src, adUnit});
+ const iframeEl = injectAndReturnIframe({
+ src,
+ divId,
+ size,
+ attributes: {
+ 'scrolling': 'no',
+ 'style': 'border: none',
+ 'allow': 'attribution-reporting; run-ad-auction',
+ },
+ });
+ // Post-message the adUnit config to the injected iframe.
+ adUnit.pageURL = location.href;
+ adUnit.pageTitle = document.title;
+ adUnit.userAgent = navigator.userAgent;
+ adUnit.isMobile = navigator.userAgentData.mobile;
+ adUnit.platform = navigator.userAgentData.platform;
+ adUnit.browserVersion = navigator.userAgentData.brands.find(
+ (brand) => 'Chromium' === brand.brand,
+ ).version;
+ iframeEl.addEventListener('load', () => {
+ iframeEl.contentWindow.postMessage(
+ JSON.stringify({
+ adUnit,
+ otherSellers,
+ }),
+ '*',
+ );
+ log('post-messaged adUnit configs', {adUnit, iframeEl});
+ });
+ log('delivering for validated adUnit', {adUnit, iframeEl});
+ }
+ };
+
+ /** Main function. */
+ (() => {
+ // Read page ad unit configurations from local storage.
+ if (!window.PSDemo || !window.PSDemo.PAGE_ADS_CONFIG) {
+ return log('did not find', {key: 'window.PSDemo.PAGE_ADS_CONFIG'});
+ }
+ const {adUnits, otherSellers} = window.PSDemo.PAGE_ADS_CONFIG;
+ if (!adUnits || !adUnits.length) {
+ return log('did not find adUnits', {
+ PAGE_ADS_CONFIG: window.PSDemo.PAGE_ADS_CONFIG,
+ });
+ }
+ log('delivering ads', {adUnits, otherSellers});
+ deliverAds(adUnits, otherSellers);
+ })();
+})();
diff --git a/services/ad-tech/src/public/js/ssp/default/auction-decision-logic.js b/services/ad-tech/src/public/js/ssp/default/auction-decision-logic.js
new file mode 100644
index 00000000..a39b0979
--- /dev/null
+++ b/services/ad-tech/src/public/js/ssp/default/auction-decision-logic.js
@@ -0,0 +1,216 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This is the 'default' auction decision logic for an SSP.
+ *
+ * What does this script do:
+ * This script is referenced in auction configurations to choose among bids
+ * in a Protected Audience auction.
+ */
+
+// ********************************************************
+// Helper Functions
+// ********************************************************
+CURR_HOST = '';
+AUCTION_ID = '';
+/** Logs to console. */
+function log(message, context) {
+ console.log(
+ '[PSDemo] Seller',
+ CURR_HOST,
+ 'decision logic',
+ AUCTION_ID,
+ message,
+ JSON.stringify({context}, ' ', ' '),
+ );
+}
+
+/** Logs execution context for demonstrative purposes. */
+function logContextForDemo(message, context) {
+ const {
+ // UNUSED adMetadata,
+ // UNUSED bid,
+ auctionConfig,
+ // UNUSED trustedScoringSignals,
+ // UNUSED browserSignals,
+ } = context;
+ CURR_HOST = auctionConfig.seller.substring('https://'.length);
+ AUCTION_ID = auctionConfig.auctionSignals.auctionId;
+ log(message, context);
+ // Log reporting IDs if found.
+ const {buyerAndSellerReportingId, selectedBuyerAndSellerReportingId} =
+ context.browserSignals;
+ if (buyerAndSellerReportingId || selectedBuyerAndSellerReportingId) {
+ log('found reporting IDs', {
+ buyerAndSellerReportingId,
+ selectedBuyerAndSellerReportingId,
+ });
+ }
+}
+
+/** Checks whether the bid is below the winning contextual bid. */
+function isBidBelowAuctionFloor({
+ // UNUSED adMetadata,
+ bid,
+ auctionConfig,
+ // UNUSED trustedScoringSignals,
+ // UNUSED browserSignals,
+}) {
+ const {winningContextualBid} = auctionConfig.sellerSignals;
+ if (!winningContextualBid) {
+ return false;
+ }
+ return bid < Number(winningContextualBid.bid);
+}
+
+/** Checks real-time signals to see whether the ad creative is blocked. */
+function isCreativeBlocked(scoringContext) {
+ const {
+ // UNUSED adMetadata,
+ // UNUSED bid,
+ auctionConfig,
+ trustedScoringSignals,
+ browserSignals,
+ } = scoringContext;
+ const {excludeCreativeTag} = auctionConfig.sellerSignals;
+ if (!excludeCreativeTag) {
+ return false; // No creative tags to exclude
+ }
+ const {renderURL} = browserSignals;
+ if (trustedScoringSignals && trustedScoringSignals.renderURL[renderURL]) {
+ const parsedScoringSignals = JSON.parse(
+ trustedScoringSignals.renderURL[renderURL],
+ );
+ if (
+ parsedScoringSignals &&
+ parsedScoringSignals.tags &&
+ parsedScoringSignals.tags.includes(excludeCreativeTag)
+ ) {
+ // Creative tag is to be excluded, reject bid.
+ log('rejecting bid blocked by publisher', {
+ parsedScoringSignals,
+ trustedScoringSignals,
+ renderURL,
+ buyer: browserSignals.interestGroupOwner,
+ dataVersion: browserSignals.dataVersion,
+ scoringContext,
+ });
+ return true;
+ }
+ }
+ return false;
+}
+
+/** Checks whether the bid includes a valid and eligible deal ID. */
+function doesBidHaveEligibleDeal({
+ // UNUSED adMetadata,
+ // UNUSED bid,
+ auctionConfig,
+ // UNUSED trustedScoringSignals,
+ browserSignals,
+}) {
+ const {availableDeals} = auctionConfig.auctionSignals;
+ if (!availableDeals || !availableDeals.length) {
+ return false; // No deals available.
+ }
+ const {selectedBuyerAndSellerReportingId} = browserSignals;
+ return availableDeals.includes(selectedBuyerAndSellerReportingId);
+}
+
+// ********************************************************
+// Top-level decision logic functions
+// ********************************************************
+function scoreAd(
+ adMetadata,
+ bid,
+ auctionConfig,
+ trustedScoringSignals,
+ browserSignals,
+) {
+ const scoringContext = {
+ adMetadata,
+ bid,
+ auctionConfig,
+ trustedScoringSignals,
+ browserSignals,
+ };
+ logContextForDemo('scoreAd()', scoringContext);
+ // Initialize ad score defaulting to a first-price auction.
+ const score = {
+ desirability: bid,
+ allowComponentAuction: true,
+ };
+ // Check if ad creative is blocked.
+ if (isCreativeBlocked(scoringContext)) {
+ score.desirability = 0;
+ score.rejectReason = 'disapproved-by-exchange';
+ log('rejecting bid with blocked creative', scoringContext);
+ return score;
+ }
+ // Check if DSP responded with an eligible deal ID.
+ const bidHasEligibleDeal = doesBidHaveEligibleDeal(scoringContext);
+ const {strictRejectForDeals} = auctionConfig.auctionSignals;
+ if (strictRejectForDeals && !bidHasEligibleDeal) {
+ // Only accepting bids with eligible bids.
+ score.desirability = 0;
+ score.rejectReason = 'invalid-bid';
+ log('rejecting bid with ineligible deal', scoringContext);
+ return score;
+ } else if (bidHasEligibleDeal) {
+ // Boost desirability score by 10 points for bids with eligible deals.
+ score.desirability = bid + 10.0;
+ log('boosting bid with eligible deal', scoringContext);
+ return score;
+ }
+ // Check if bid is below auction floor.
+ if (isBidBelowAuctionFloor(scoringContext)) {
+ score.desirability = 0;
+ score.rejectReason = 'bid-below-auction-floor';
+ return score;
+ }
+ // In all other cases, default to a first-price auction.
+ return score;
+}
+
+function reportResult(auctionConfig, browserSignals) {
+ logContextForDemo('reportResult()', {auctionConfig, browserSignals});
+ const reportingContext = {
+ auctionId: AUCTION_ID,
+ pageURL: auctionConfig.auctionSignals.pageURL,
+ topLevelSeller: browserSignals.topLevelSeller,
+ winningBuyer: browserSignals.interestGroupOwner,
+ renderURL: browserSignals.renderURL,
+ bid: browserSignals.bid,
+ bidCurrency: browserSignals.bidCurrency,
+ buyerAndSellerReportingId: browserSignals.buyerAndSellerReportingId,
+ selectedBuyerAndSellerReportingId:
+ browserSignals.selectedBuyerAndSellerReportingId,
+ };
+ let reportUrl = auctionConfig.seller + '/reporting?report=result';
+ for (const [key, value] of Object.entries(reportingContext)) {
+ reportUrl = `${reportUrl}&${key}=${value}`;
+ }
+ sendReportTo(reportUrl);
+ return /* sellerSignals= */ {
+ success: true,
+ auctionId: AUCTION_ID,
+ buyer: browserSignals.interestGroupOwner,
+ reportUrl: auctionConfig.seller + '/reporting',
+ signalsForWinner: {signalForWinner: 1},
+ };
+}
diff --git a/services/ad-tech/src/public/js/ssp/default/top-level-auction-decision-logic.js b/services/ad-tech/src/public/js/ssp/default/top-level-auction-decision-logic.js
new file mode 100644
index 00000000..e8ca94ca
--- /dev/null
+++ b/services/ad-tech/src/public/js/ssp/default/top-level-auction-decision-logic.js
@@ -0,0 +1,124 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This is the 'default' auction decision logic for an SSP.
+ *
+ * What does this script do:
+ * This script is referenced in auction configurations to choose among bids
+ * in a Protected Audience auction.
+ */
+
+// ********************************************************
+// Helper Functions
+// ********************************************************
+CURR_HOST = '';
+AUCTION_ID = '';
+/** Logs to console. */
+function log(msg, context) {
+ console.log(
+ '[PSDemo] Top-level Seller',
+ CURR_HOST,
+ 'decision logic',
+ AUCTION_ID,
+ msg,
+ JSON.stringify({context}, ' ', ' '),
+ );
+}
+
+/** Logs execution context for demonstrative purposes. */
+function logContextForDemo(message, context) {
+ const {
+ // UNUSED adMetadata,
+ // UNUSED bid,
+ auctionConfig,
+ // UNUSED trustedScoringSignals,
+ browserSignals,
+ } = context;
+ CURR_HOST = auctionConfig.seller.substring('https://'.length);
+ const winningComponentSeller = browserSignals.componentSeller;
+ const winningComponentAuctionConfig = auctionConfig.componentAuctions.find(
+ (componentAuction) => winningComponentSeller === componentAuction.seller,
+ );
+ AUCTION_ID = winningComponentAuctionConfig.auctionSignals.auctionId;
+ log(message, context);
+ // Log reporting IDs if found.
+ const {buyerAndSellerReportingId, selectedBuyerAndSellerReportingId} =
+ context.browserSignals;
+ if (buyerAndSellerReportingId || selectedBuyerAndSellerReportingId) {
+ log('found reporting IDs', {
+ buyerAndSellerReportingId,
+ selectedBuyerAndSellerReportingId,
+ });
+ }
+}
+
+// ********************************************************
+// Top-level decision logic functions
+// ********************************************************
+function scoreAd(
+ adMetadata,
+ bid,
+ auctionConfig,
+ trustedScoringSignals,
+ browserSignals,
+) {
+ logContextForDemo('scoreAd()', {
+ adMetadata,
+ bid,
+ auctionConfig,
+ trustedScoringSignals,
+ browserSignals,
+ });
+ return {
+ desirability: bid,
+ allowComponentAuction: true,
+ // incomingBidInSellerCurrency: optional
+ };
+}
+
+function reportResult(auctionConfig, browserSignals) {
+ logContextForDemo('reportResult()', {auctionConfig, browserSignals});
+ const winningComponentSeller = browserSignals.componentSeller;
+ const winningComponentAuctionConfig = auctionConfig.componentAuctions.find(
+ (componentAuction) => winningComponentSeller === componentAuction.seller,
+ );
+ const reportingContext = {
+ auctionId: AUCTION_ID,
+ pageURL: winningComponentAuctionConfig.auctionSignals.pageURL,
+ winningComponentSeller,
+ winningBuyer: browserSignals.interestGroupOwner,
+ renderURL: browserSignals.renderURL,
+ bid: browserSignals.bid,
+ bidCurrency: browserSignals.bidCurrency,
+ buyerAndSellerReportingId: browserSignals.buyerAndSellerReportingId,
+ selectedBuyerAndSellerReportingId:
+ browserSignals.selectedBuyerAndSellerReportingId,
+ };
+ let reportUrl = auctionConfig.seller + '/reporting?report=result';
+ for (const [key, value] of Object.entries(reportingContext)) {
+ reportUrl = `${reportUrl}&${key}=${value}`;
+ }
+ sendReportTo(reportUrl);
+ return {
+ success: true,
+ auctionId: AUCTION_ID,
+ buyer: browserSignals.interestGroupOwner,
+ reportUrl: auctionConfig.seller + '/reporting',
+ signalsForWinner: {signalForWinner: 1},
+ };
+}
diff --git a/services/ad-tech/src/public/js/ssp/run-sequential-ad-auction.js b/services/ad-tech/src/public/js/ssp/run-sequential-ad-auction.js
new file mode 100644
index 00000000..c339a718
--- /dev/null
+++ b/services/ad-tech/src/public/js/ssp/run-sequential-ad-auction.js
@@ -0,0 +1,267 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+(() => {
+ const CURR_SCRIPT_URL = new URL(document.currentScript.src);
+ let CURR_AUCTION_ID = '';
+ // ****************************************************************
+ // HELPER FUNCTIONS
+ // ****************************************************************
+ /** Logs to console. */
+ const log = (message, context) => {
+ console.log(
+ '[PSDemo] Seller',
+ CURR_SCRIPT_URL.hostname,
+ 'sequential auction runner',
+ CURR_AUCTION_ID,
+ message,
+ {context},
+ );
+ };
+
+ /** Validates the post messages and returns the adUnit and other sellers. */
+ const getValidatedAdUnitAndOtherSellers = (message) => {
+ const iframeUrl = new URL(window.location.href);
+ const publisher = iframeUrl.searchParams.get('publisher');
+ if (message.origin !== publisher) {
+ log('ignoring message from unknown origin', {message, publisher});
+ return [];
+ }
+ try {
+ const {adUnit, otherSellers} = JSON.parse(message.data);
+ if (!adUnit.adType) {
+ log('stopping as adType not found in adUnit', {adUnit});
+ return [];
+ }
+ if (!otherSellers || !otherSellers.length) {
+ log('did not find other sellers', {adUnit, otherSellers});
+ return [adUnit, []];
+ }
+ return [adUnit, otherSellers];
+ } catch (e) {
+ log('encountered error in parsing adUnit config', {message});
+ return [];
+ }
+ };
+
+ /** Builds and returns the various bid request URLs. */
+ const getBidRequestUrlsWithContext = (adUnit, sellers) => {
+ const auctionId = adUnit.auctionId || `HB-${crypto.randomUUID()}`;
+ if (!adUnit.auctionId) {
+ adUnit.auctionId = auctionId;
+ }
+ const bidRequestQuery = Object.entries(adUnit)
+ .map(([key, value]) => `${key}=${value}`)
+ .join('&');
+ const bidRequestUrls = [];
+ for (const seller of sellers) {
+ const bidRequest = new URL(seller);
+ bidRequest.pathname = '/ssp/contextual-bid';
+ bidRequestUrls.push(`${bidRequest.toString()}?${bidRequestQuery}`);
+ }
+ return bidRequestUrls;
+ };
+
+ /** Fetches all the contextual bid responses with a timeout. */
+ const getAllContextualBidResponses = async (adUnit, sellers) => {
+ const bidRequestUrls = getBidRequestUrlsWithContext(adUnit, sellers);
+ const bidResponsePromises = bidRequestUrls.map(async (bidRequestUrl) => {
+ log('making contextual bid request', {bidRequestUrl});
+ const response = await fetch(bidRequestUrl);
+ if (response.ok) {
+ const bidResponse = await response.json();
+ log('received contextual bid response', {bidResponse});
+ return bidResponse;
+ } else {
+ log('encountered error in contextual bid response', {
+ statusText: response.statusText,
+ bidRequestUrl,
+ });
+ return {bid: '0.0'};
+ }
+ });
+ // Use Promise.race to implement the timeout.
+ const bidResponses = await Promise.race([
+ (await Promise.allSettled(bidResponsePromises))
+ .filter((p) => p.status === 'fulfilled')
+ .map((p) => p.value),
+ new Promise((resolve) =>
+ setTimeout(() => resolve([]), CONTEXTUAL_AUCTION_TIMEOUT_MS),
+ ),
+ ]);
+ return bidResponses;
+ };
+
+ /** Assembles and returns a multi-seller auction configuration. */
+ const assembleAuctionConfig = (
+ adUnit,
+ winningContextualBid,
+ componentAuctions,
+ ) => {
+ const decisionLogicURL = (() => {
+ const url = new URL(CURR_SCRIPT_URL.origin);
+ url.pathname = '/js/ssp/default/top-level-auction-decision-logic.js';
+ return url.toString();
+ })();
+ const trustedScoringSignalsURL = (() => {
+ const url = new URL(CURR_SCRIPT_URL.origin);
+ url.pathname = '/ssp/realtime-signals/scoring-signal.json';
+ return url.toString();
+ })();
+ return {
+ seller: CURR_SCRIPT_URL.origin,
+ decisionLogicURL,
+ trustedScoringSignalsURL,
+ // 'maxTrustedScoringSignalsURLLength': 10000,
+ sellerSignals: {
+ adUnit,
+ winningContextualBid,
+ },
+ sellerCurrency: 'USD',
+ // deprecatedRenderURLReplacements: {},
+ resolveToConfig: adUnit.isFencedFrame,
+ // signal: AbortSignal,
+ componentAuctions,
+ };
+ };
+
+ // ****************************************************************
+ // PROTECTED AUDIENCE: RUN AD AUCTION
+ // ****************************************************************
+ /** Executes the PAAPI auction in sequence and returns the overall result. */
+ const executeSequentialAuction = async (adUnit, contextualBidResponses) => {
+ const [winningContextualBid] = contextualBidResponses
+ .filter((bid) => Number(bid.bid) > 0)
+ .sort((bid1, bid2) => Number(bid2.bid) - Number(bid1.bid));
+ const componentAuctionConfigs = contextualBidResponses.map(
+ (bidResponse) => bidResponse.componentAuctionConfig,
+ );
+ const auctionConfig = assembleAuctionConfig(
+ adUnit,
+ winningContextualBid,
+ componentAuctionConfigs,
+ );
+ log('executing sequential auction', {
+ adUnit,
+ winningContextualBid,
+ auctionConfig,
+ });
+ const adAuctionResult = await navigator.runAdAuction(auctionConfig);
+ if (adAuctionResult) {
+ log('delivering Protected Audience ad', {adAuctionResult});
+ return {
+ type: 'PROTECTED_AUDIENCE',
+ value: adAuctionResult,
+ };
+ } else if (winningContextualBid) {
+ log('delivering contextual ad', {winningContextualBid});
+ return {
+ type: 'CONTEXTUAL',
+ value: winningContextualBid.renderURL,
+ };
+ } else {
+ document.getElementById('ad-label').innerText = 'No eligible ads found.';
+ log('found no eligible ads', {adUnit, auctionConfig});
+ return {
+ type: 'NONE',
+ };
+ }
+ };
+
+ // ****************************************************************
+ // POST-MESSAGE LISTENER
+ // ****************************************************************
+ /** Executes the multi-seller ad auction for the given adUnit config. */
+ const runMultiSellerAdAuction = async (message) => {
+ const [adUnit, otherSellers] = getValidatedAdUnitAndOtherSellers(message);
+ if (!adUnit) {
+ return;
+ }
+ const {auctionId} = adUnit;
+ CURR_AUCTION_ID = auctionId;
+ const contextualBidResponses = await getAllContextualBidResponses(
+ adUnit,
+ [location.origin, ...otherSellers], // Explicitly include self.
+ );
+ if (!contextualBidResponses || !contextualBidResponses.length) {
+ return log('received no contextual bid responses', {
+ adUnit,
+ otherSellers,
+ });
+ }
+ const adAuctionResult = await executeSequentialAuction(
+ adUnit,
+ contextualBidResponses,
+ );
+ let adFrame;
+ const {isFencedFrame} = adUnit;
+ if ('NONE' === adAuctionResult.type) {
+ return;
+ } else if ('CONTEXTUAL' === adAuctionResult.type) {
+ // FencedFrames can only be intialized with a FencedFrameConfig, and a
+ // FencedFrameConfig constructor isn't currently exposed to JavaScript.
+ // As a result, contextual ads can't be shown in FencedFrames without
+ // using the following Chrome flag:
+ // chrome://flags/#enable-fenced-frames-developer-mode
+ // See: https://github.com/WICG/fenced-frame/blob/master/explainer/use_cases.md#manual-construction-for-general-purpose-usage-and-testing
+ if (isFencedFrame) {
+ log('forcing render in iframe for contextual ad', {
+ adUnit,
+ adAuctionResult,
+ });
+ }
+ // As such, render contextual ad in iframes regardless of adUnit config.
+ adFrame = document.createElement('iframe');
+ adFrame.src = adAuctionResult.value;
+ } else if ('PROTECTED_AUDIENCE' === adAuctionResult.type) {
+ if (isFencedFrame) {
+ adFrame = document.createElement('fencedframe');
+ adFrame.config = adAuctionResult.value;
+ } else {
+ adFrame = document.createElement('iframe');
+ adFrame.src = adAuctionResult.value;
+ }
+ } else {
+ log('auction result type not implemented', {adUnit, adAuctionResult});
+ return;
+ }
+ const {size} = adUnit;
+ [adFrame.width, adFrame.height] = size;
+ adFrame.addEventListener('load', () => {
+ adFrame.contentWindow.postMessage(
+ JSON.stringify({
+ auctionId,
+ seller: location.hostname,
+ }),
+ '*',
+ );
+ });
+ log('rendering ad', {adUnit, otherSellers, adAuctionResult, adFrame});
+ document.body.appendChild(adFrame);
+ };
+
+ // ****************************************************************
+ // MAIN FUNCTION
+ // ****************************************************************
+ (() => {
+ if (!navigator.runAdAuction) {
+ return log('stopping becuase Protected Audience is not supported', {});
+ }
+ // Wait for adUnit object to be post-messaged by ad server tag.
+ window.addEventListener('message', runMultiSellerAdAuction);
+ log('multi-seller waiting for adUnit configs', {});
+ })();
+})();
diff --git a/services/ad-tech/src/public/js/ssp/run-simple-ad-auction.js b/services/ad-tech/src/public/js/ssp/run-simple-ad-auction.js
new file mode 100644
index 00000000..cf6c9084
--- /dev/null
+++ b/services/ad-tech/src/public/js/ssp/run-simple-ad-auction.js
@@ -0,0 +1,116 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This script is loaded on the publisher page to run a single-seller
+ * Protected Audience auction.
+ *
+ * What does this script do:
+ * This script reads the ad unit configurations set by the publisher and
+ * fetches the auction configurations from its server to directly execute the
+ * Protected Audience without a contextual auction.
+ */
+const runSimpleAdAuction = async () => {
+ /** Domain of the current script. */
+ const CURR_HOSTNAME = '<%= HOSTNAME %>';
+ // ****************************************************************
+ // HELPER FUNCTIONS
+ // ****************************************************************
+ /** Logs to console. */
+ const log = (message, context) => {
+ console.log(
+ '[PSDemo] Seller',
+ CURR_HOSTNAME,
+ 'PAAPI auction runner',
+ message,
+ {context},
+ );
+ };
+
+ /** Makes a request to the server to retrieve an auction config. */
+ const getAuctionConfig = async (adUnit) => {
+ const auctionConfigUrl = new URL(
+ `https://${CURR_HOSTNAME}/ssp/auction-config.json`,
+ );
+ // Copy over ad unit parameters
+ for (const [key, value] of Object.entries(adUnit)) {
+ auctionConfigUrl.searchParams.append(key, value);
+ }
+ // Copy query params from current context.
+ const currentUrl = new URL(location.href);
+ for (const [key, value] of currentUrl.searchParams) {
+ if (auctionConfigUrl.searchParams.has(key)) {
+ log('INTERNAL overwriting query parameter', {
+ key,
+ oldValue: auctionConfigUrl.searchParams.get(key),
+ newValue: value,
+ url: auctionConfigUrl.toString(),
+ });
+ }
+ auctionConfigUrl.searchParams.append(key, value);
+ }
+ log('retrieving auction config', {auctionConfigUrl});
+ const res = await fetch(auctionConfigUrl);
+ if (res.ok) {
+ const auctionConfig = await res.json();
+ log('retrieved auction config', {auctionConfig});
+ return auctionConfig;
+ } else {
+ log('encountered error in fetching auction config', {
+ status: res.statusText,
+ });
+ }
+ };
+
+ // ****************************************************************
+ // PROTECTED AUDIENCE : RUN AD AUCTION
+ // ****************************************************************
+ if (!navigator.runAdAuction) {
+ return log('stopping because Protected Audience is not supported', {});
+ }
+ const [adUnit] = window.PSDemo.PAGE_ADS_CONFIG.adUnits;
+ const auctionConfig = await getAuctionConfig(adUnit);
+ log('starting Protected Audience auction', {auctionConfig});
+ const adAuctionResult = await navigator.runAdAuction(auctionConfig);
+ if (!adAuctionResult) {
+ log("didn't get a Protected Audience result", {
+ auctionConfig,
+ adAuctionResult,
+ });
+ document.getElementById(adUnit.divId).innerText = 'No eligible ads';
+ } else {
+ log('got Protected Audience result', {auctionConfig, adAuctionResult});
+ const adFrame = document.createElement('fencedframe');
+ adFrame.config = adAuctionResult;
+ [adFrame.width, adFrame.height] = adUnit.size;
+ log('delivering ads in ', {
+ adFrame,
+ adUnit,
+ auctionConfig,
+ adAuctionResult,
+ });
+ document.getElementById(adUnit.divId).appendChild(adFrame);
+ }
+};
+
+// Finally, execute the above function when DOM is loaded or execute
+// immediately if DOM is already loaded.
+if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', runSimpleAdAuction);
+} else {
+ runSimpleAdAuction();
+}
diff --git a/services/ad-tech/src/public/js/video-ad-frame.js b/services/ad-tech/src/public/js/video-ad-frame.js
new file mode 100644
index 00000000..edec0930
--- /dev/null
+++ b/services/ad-tech/src/public/js/video-ad-frame.js
@@ -0,0 +1,124 @@
+/*
+ Copyright 2022 Google LLC
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ * Where is this script used:
+ * This script is loaded inside the Protected Audience renderURL frame for a
+ * video ad. For video ads, this renderURL frame is hidden because the video
+ * ad is loaded on the video player on the publisher page.
+ *
+ * What does this script do:
+ * This script post-messages the VAST XML content to configure ads in the
+ * video player.
+ */
+(async () => {
+ /** VAST XML representing the video ad to be served. */
+ const DSP_VAST_URI = encodeURIComponent(
+ 'https://pubads.g.doubleclick.net/gampad/ads?' +
+ 'iu=/21775744923/external/single_ad_samples&sz=640x480&' +
+ 'cust_params=sample_ct%3Dlinear&ciu_szs=300x250%2C728x90&' +
+ 'gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&' +
+ 'impl=s&correlator=',
+ );
+
+ /** Finds and returns SSP's VAST XML URL in renderURL query parameters. */
+ const getSspVastQueryFromCurrentUrl = () => {
+ const currentUrl = new URL(location.href);
+ const sspVastQuery = currentUrl.searchParams.get('sspVast');
+ if (!sspVastQuery) {
+ return console.log('[PSDemo] Expected sspVast query in renderURL', {
+ url: location.href,
+ queryParam: 'sspVast',
+ });
+ }
+ return decodeURIComponent(sspVastQuery);
+ };
+
+ /** Fetches the final VAST XML content from the SSP. */
+ const fetchFinalizedVastXmlFromSsp = async (sspVast, auctionId) => {
+ // The SSP's endpoint accepts two query parameters -- dspVast, auctionId --
+ // which the SSP embeds in the finalized VAST XML.
+ const sspVastUrl = new URL(sspVast);
+ sspVastUrl.searchParams.append('auctionId', auctionId);
+ sspVastUrl.searchParams.append('dspVast', DSP_VAST_URI);
+ // Copy query parameters from renderURL.
+ const currentUrl = new URL(location.href);
+ for (const [key, value] of Object.entries(currentUrl.searchParams)) {
+ if ('sspVast' === key) {
+ continue;
+ }
+ sspVastUrl.searchParams.append(key, value);
+ }
+ // Fetch the finalized VAST XML from the ad serving SSP.
+ const response = await fetch(sspVastUrl);
+ const result = await response.text();
+ return result;
+ };
+
+ /** Adds a descriptive label about the involved ad-techs. */
+ const addDescriptionToAdContainer = (sspVast) => {
+ const seller = new URL(sspVast).hostname;
+ const buyer = location.hostname;
+ const $adLabel = document.getElementById('ad-label');
+ if ($adLabel) {
+ $adLabel.innerText = `Video ad from ${buyer} delivered by ${seller}`;
+ }
+ };
+
+ // **************************************************************************
+ // MAIN FUNCTION
+ // **************************************************************************
+ (() => {
+ // The rendering process begins when the frame receives the auctionId.
+ window.addEventListener('message', async (message) => {
+ if (!message.origin.startsWith('https://<%= DEMO_HOST_PREFIX %>')) {
+ return console.log(
+ '[PSDemo] Ignoring message from unknonw origin',
+ message,
+ );
+ }
+ try {
+ const {auctionId} = JSON.parse(message.data);
+ if (!auctionId || 'string' !== typeof auctionId) {
+ return console.log('[PSDemo] auctionId not found', {message});
+ }
+ const sspVast = getSspVastQueryFromCurrentUrl();
+ const vastXmlText = await fetchFinalizedVastXmlFromSsp(
+ sspVast,
+ auctionId,
+ );
+ if (vastXmlText) {
+ addDescriptionToAdContainer(sspVast);
+ // The finalized VAST XML is messaged to the top-most frame that will
+ // pass the VAST XML to the video player
+ const {0: containerFrame} = window.top.frames;
+ containerFrame.top.postMessage(
+ JSON.stringify({
+ auctionId,
+ buyer: location.hostname,
+ vastXml: vastXmlText.toString(),
+ }),
+ '*',
+ );
+ } else {
+ console.log('[PSDemo] Could not fetch VAST XML', {auctionId});
+ }
+ } catch (e) {
+ console.log('[PSDemo] Encountered error delivering video ad', {e});
+ }
+ });
+ })();
+})();
diff --git a/services/ad-tech/src/routes/common/ads-router.ts b/services/ad-tech/src/routes/common/ads-router.ts
new file mode 100644
index 00000000..3deb5c48
--- /dev/null
+++ b/services/ad-tech/src/routes/common/ads-router.ts
@@ -0,0 +1,64 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {
+ getContextualAdTemplateVariables,
+ getInterestGroupAdTemplateVariables,
+ getStaticAdTemplateVariables,
+} from '../../lib/common-utils.js';
+
+/**
+ * This router is responsible for handling requests to serve ads, i.e. the ad
+ * itself. These endpoints don't execute any selection logic. The URL should
+ * be sufficient to point to a specific ad creative, using query parameters if
+ * disambiguation is needed.
+ *
+ * Path: /ads/
+ */
+export const AdsRouter = express.Router();
+
+// ************************************************************************
+// HTTP handlers
+// ************************************************************************
+/** Used as render URL in interest groups for display ads. */
+AdsRouter.get('/display-ads', async (req: Request, res: Response) => {
+ const templateVariables = getInterestGroupAdTemplateVariables(req.query);
+ console.log('Loading interest group ad', templateVariables);
+ res
+ .set('Allow-Fenced-Frame-Automatic-Beacons', 'true')
+ .render('display-ad-frame', templateVariables);
+});
+
+/** Used as render URL for contextual ads or static ads. */
+AdsRouter.get('/contextual-ads', async (req: Request, res: Response) => {
+ const templateVariables = getContextualAdTemplateVariables();
+ console.log('Loading contextual ad', templateVariables);
+ res.render('contextual-ad-frame', templateVariables);
+});
+
+/** Used as render URL in interest groups for video ads. */
+AdsRouter.get('/video-ads', async (req: Request, res: Response) => {
+ console.log('Loading video ad', req.query);
+ res.render('video-ad-frame');
+});
+
+/** Used as render URL for Multi Touch Attribution ads. */
+AdsRouter.get('/static-ads', async (req: Request, res: Response) => {
+ console.log('Loading MTA ad', req.query);
+ const templateVariables = getStaticAdTemplateVariables(
+ req.query,
+ req.headers,
+ );
+ res.render('static-ad-frame', templateVariables);
+});
diff --git a/services/ad-tech/src/routes/common/attribution-reporting-router.ts b/services/ad-tech/src/routes/common/attribution-reporting-router.ts
new file mode 100644
index 00000000..be2cce78
--- /dev/null
+++ b/services/ad-tech/src/routes/common/attribution-reporting-router.ts
@@ -0,0 +1,96 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {decodeDict} from 'structured-field-values';
+import {
+ getAttributionSourceHeaders,
+ getAttributionTriggerHeaders,
+ getAttributionRedirectUrl,
+} from '../../lib/attribution-reporting-helper.js';
+import {getStructuredObject} from '../../lib/common-utils.js';
+
+/**
+ * This router is resposible for handling requests related to the Attribution
+ * Reporting API. These could be requests from ad impressions to register an
+ * attribution source or at conversions to trigger attribution.
+ *
+ * Note that there are additional requests that are eligible to register
+ * attribution sources, such as the Protected Audience ad beacon reports
+ * triggered via the Fenced Frames Ads Reporting API. Both of these HTTP
+ * handlers use the same helper library to handle the attribution headers.
+ *
+ * Path: /attribution/
+ */
+export const AttributionReportingRouter = express.Router();
+
+// ************************************************************************
+// HTTP handlers
+// ************************************************************************
+/** Registers a click or view attribution source (impression). */
+AttributionReportingRouter.get(
+ '/register-source',
+ async (req: Request, res: Response) => {
+ if (!('attribution-reporting-eligible' in req.headers)) {
+ console.log(
+ '[ARA] Request is not eligible for attribution reporting.',
+ req.originalUrl,
+ );
+ res
+ .status(400)
+ .send('Request is not eligible for attribution reporting.');
+ return;
+ }
+ const queryParams = getStructuredObject(req.query);
+ const attributionEligibleHeader = decodeDict(
+ req.headers['attribution-reporting-eligible'] as string,
+ );
+ const sourceHeaders = getAttributionSourceHeaders(
+ queryParams,
+ attributionEligibleHeader,
+ );
+ if (sourceHeaders) {
+ res.setHeader(
+ 'Attribution-Reporting-Register-Source',
+ JSON.stringify(sourceHeaders),
+ );
+ }
+ const redirectUrl = getAttributionRedirectUrl(queryParams);
+ if (redirectUrl) {
+ console.log('[ARA] Following redirect chain: ', redirectUrl);
+ res.redirect(redirectUrl);
+ return;
+ }
+ if (sourceHeaders) {
+ res
+ .status(200)
+ .send(`Attribution source registered: ${JSON.stringify(req.query)}`);
+ } else {
+ res.status(400).send('Attribution reporting header is malformed.');
+ }
+ },
+);
+
+/** Registers an attribution trigger (conversion). */
+AttributionReportingRouter.get(
+ '/register-trigger',
+ async (req: Request, res: Response) => {
+ const queryParams = getStructuredObject(req.query);
+ const triggerHeaders = getAttributionTriggerHeaders(queryParams);
+ res.setHeader(
+ 'Attribution-Reporting-Register-Trigger',
+ JSON.stringify(triggerHeaders),
+ );
+ res.sendStatus(200);
+ },
+);
diff --git a/services/ad-tech/src/routes/common/common-router.ts b/services/ad-tech/src/routes/common/common-router.ts
new file mode 100644
index 00000000..d4474665
--- /dev/null
+++ b/services/ad-tech/src/routes/common/common-router.ts
@@ -0,0 +1,109 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import ejs from 'ejs';
+import express, {NextFunction, Request, Response} from 'express';
+import {
+ DEMO_HOST_PREFIX,
+ JAVASCRIPT_TEMPLATE_VARIABLES,
+} from '../../lib/constants.js';
+import {getTemplateVariables} from '../../lib/common-utils.js';
+
+/**
+ * This router is responsible for registering HTTP headers, preflight requests,
+ * and serve the index page which isn't used in use-case journeys.
+ *
+ * Path: /
+ */
+export const CommonRouter = express.Router();
+
+// ************************************************************************
+// HTTP Header Configurations
+// ************************************************************************
+CommonRouter.use((req: Request, res: Response, next: NextFunction) => {
+ // Explicitly allow loading in fenced-frame.
+ if (req.get('Sec-Fetch-Dest') === 'fencedframe') {
+ res.setHeader('Supports-Loading-Mode', 'fenced-frame');
+ }
+ // Enable debug reports for Atribution Reporting.
+ res.cookie('ar_debug', '1', {
+ sameSite: 'none',
+ secure: true,
+ httpOnly: true,
+ });
+ // Enable CORS.
+ if (req.headers.origin?.startsWith(`https://${DEMO_HOST_PREFIX}`)) {
+ res.setHeader('Access-Control-Allow-Origin', req.headers.origin!);
+ res.setHeader('Access-Control-Allow-Credentials', 'true');
+ res.setHeader('Access-Control-Private-Network', 'true');
+ }
+ // Observe browsing topics.
+ res.setHeader('Observe-Browsing-Topics', '?1');
+ next();
+});
+
+// ************************************************************************
+// HTTP handlers for static content
+// ************************************************************************
+/** Custom handler to use EJS renderer for JavaScript files. */
+CommonRouter.get('/js/*.js', (req: Request, res: Response) => {
+ const filePath = `src/public${req.path}`;
+ if (
+ filePath.endsWith('bidding-logic.js') ||
+ filePath.endsWith('decision-logic.js')
+ ) {
+ res.set('X-Allow-FLEDGE', 'true');
+ res.set('Ad-Auction-Allowed', 'true');
+ }
+ if (filePath.endsWith('/run-ad-auction.js')) {
+ res.set('Supports-Loading-Mode', 'fenced-frame');
+ res.set('Permissions-Policy', 'run-ad-auction=(*)');
+ }
+ res.set('Content-Type', 'application/javascript');
+ ejs.renderFile(filePath, JAVASCRIPT_TEMPLATE_VARIABLES, (err, content) => {
+ if (err) {
+ console.log('Encountered error rendering static JS', {
+ filePath,
+ JAVASCRIPT_TEMPLATE_VARIABLES,
+ err,
+ });
+ res.status(500).send();
+ return;
+ }
+ if (content) {
+ res.send(content);
+ } else {
+ res.status(404).send();
+ }
+ });
+});
+
+/** Handler for all other static content: CSS, IMG. */
+CommonRouter.use(express.static('src/public'));
+
+// ************************************************************************
+// Other common HTTP handlers
+// ************************************************************************
+/** Handler for pre-flight OPTIONS requests. */
+CommonRouter.options('*', (req: Request, res: Response) => {
+ if (req.headers.origin?.startsWith(`https://${DEMO_HOST_PREFIX}`)) {
+ res.setHeader('Access-Control-Allow-Origin', req.headers.origin!);
+ res.setHeader('Access-Control-Private-Network', 'true');
+ res.sendStatus(200);
+ }
+});
+
+/** Index page, not commonly used in tests. */
+CommonRouter.get('/', async (req: Request, res: Response) => {
+ res.render('index', getTemplateVariables());
+});
diff --git a/services/ad-tech/src/routes/common/report-router.ts b/services/ad-tech/src/routes/common/report-router.ts
new file mode 100644
index 00000000..076a2923
--- /dev/null
+++ b/services/ad-tech/src/routes/common/report-router.ts
@@ -0,0 +1,135 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {
+ Report,
+ ReportCategory,
+ ReportStore,
+} from '../../controllers/report-store.js';
+import {
+ getAttributionSourceHeaders,
+ getAttributionRedirectUrl,
+} from '../../lib/attribution-reporting-helper.js';
+import {
+ getStructuredObject,
+ getTemplateVariables,
+} from '../../lib/common-utils.js';
+import {decodeDict} from 'structured-field-values';
+
+/**
+ * This router is responsible for handling event-level report requests
+ * generated typically from Protected Audience auctions, such as via
+ * sendReportTo() from reportResult() or reportWin(), ad beacons with the
+ * Fenced Frames Ads Reporting API or trackingEvents included in the VAST XML.
+ *
+ * Path: /reporting/
+ */
+export const ReportRouter = express.Router();
+
+// ************************************************************************
+// Helper functions
+// ************************************************************************
+/** Sets ARA source registration headers if request is eligible. */
+const setAttributionReportingHeaders = (req: Request, res: Response) => {
+ if ('attribution-reporting-eligible' in req.headers) {
+ const attributionEligibleHeader = decodeDict(
+ req.headers['attribution-reporting-eligible'] as string,
+ );
+ const queryParams = getStructuredObject(req.query);
+ const sourceHeaders = getAttributionSourceHeaders(
+ queryParams,
+ attributionEligibleHeader,
+ );
+ if (sourceHeaders) {
+ console.log(
+ '[ARA] Request is eligible for attribution reporting.',
+ req.originalUrl,
+ sourceHeaders,
+ );
+ res.setHeader(
+ 'Attribution-Reporting-Register-Source',
+ JSON.stringify(sourceHeaders),
+ );
+ }
+ } else {
+ console.log(
+ '[ARA] Request is not eligible for attribution reporting.',
+ req.originalUrl,
+ );
+ }
+};
+
+// ************************************************************************
+// HTTP handlers
+// ************************************************************************
+/** Receives event logs and registers attribution source if eligible. */
+ReportRouter.get('/', async (req: Request, res: Response) => {
+ const report: Report = {
+ category: ReportCategory.EVENT_LEVEL_LOG,
+ timestamp: Date.now().toString(),
+ data: req.query,
+ };
+ console.log('Event-level report received: ', req.baseUrl, report);
+ ReportStore.addReport(report);
+ setAttributionReportingHeaders(req, res);
+ const queryParams = getStructuredObject(req.query);
+ const redirectUrl = getAttributionRedirectUrl(queryParams);
+ if (redirectUrl) {
+ console.log('[ARA] Following redirect chain: ', redirectUrl);
+ res.redirect(redirectUrl);
+ return;
+ }
+ res
+ .status(200)
+ .send(`Received event-level report: ${JSON.stringify(queryParams)}`);
+});
+
+/** Receives event logs and registers attribution source if eligible. */
+ReportRouter.post('/', async (req: Request, res: Response) => {
+ const report: Report = {
+ category: ReportCategory.EVENT_LEVEL_LOG,
+ timestamp: Date.now().toString(),
+ data: {
+ ...req.query,
+ ...req.body,
+ },
+ };
+ console.log('Event-level report received: ', req.baseUrl, report);
+ ReportStore.addReport(report);
+ setAttributionReportingHeaders(req, res);
+ const queryParams = getStructuredObject(req.query);
+ const redirectUrl = getAttributionRedirectUrl(queryParams);
+ if (redirectUrl) {
+ console.log('[ARA] Following redirect chain: ', redirectUrl);
+ res.redirect(redirectUrl);
+ return;
+ }
+ res
+ .status(200)
+ .send(`Received event-level report: ${JSON.stringify(queryParams)}`);
+});
+
+// ****************************************************************************
+// This endpoint is not functionally used in use-case journeys, but rather to
+// quickly demonstrate the event-level reports the ad-tech server received
+// within the last 10 minutes.
+// ****************************************************************************
+/** Shows all reports from in-memory storage. */
+ReportRouter.get('/view-reports', async (req: Request, res: Response) => {
+ const hostDetails = getTemplateVariables('Reports');
+ res.render('view-reports', {
+ reports: ReportStore.getAllReports(),
+ ...hostDetails,
+ });
+});
diff --git a/services/ad-tech/src/routes/common/topics-router.ts b/services/ad-tech/src/routes/common/topics-router.ts
new file mode 100644
index 00000000..7f921ac0
--- /dev/null
+++ b/services/ad-tech/src/routes/common/topics-router.ts
@@ -0,0 +1,35 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+
+/**
+ * This router is responsible for handling all requests related to the Topics
+ * API. This includes requests to observe browsing topics over fetch requests
+ * using HTTP headers.
+ *
+ * Path: /topics/
+ */
+export const TopicsRouter = express.Router();
+
+// ************************************************************************
+// HTTP handlers
+// ************************************************************************
+/** TODO: Verify this use-case */
+TopicsRouter.get(
+ '/observe-browsing-topics',
+ async (req: Request, res: Response) => {
+ const browsingTopics = req.get('Sec-Browsing-Topics');
+ res.json({topics: browsingTopics});
+ },
+);
diff --git a/services/ad-tech/src/routes/dsp/bidding-signals-router.ts b/services/ad-tech/src/routes/dsp/bidding-signals-router.ts
new file mode 100644
index 00000000..8ba7a150
--- /dev/null
+++ b/services/ad-tech/src/routes/dsp/bidding-signals-router.ts
@@ -0,0 +1,107 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {query, Request, Response} from 'express';
+import {
+ BIDDING_SIGNALS_DEALS,
+ BIDDING_SIGNALS_DEFAULT,
+ HOSTNAME,
+ SHOP_HOST,
+ TRAVEL_HOST,
+} from '../../lib/constants.js';
+import {KeyValueStore} from '../../controllers/key-value-store.js';
+
+/**
+ * This router is responsible for handling requests to retrieve realtime
+ * bidding signals for on-device Protected Audience auctions. In that, this is
+ * a simplified Bring-Your-Own-Server (BYOS) implementation of the Key - Value
+ * Server for ad buyers.
+ *
+ * Path: /dsp/realtime-signals/
+ */
+export const BiddingSignalsRouter = express.Router();
+
+// ************************************************************************
+// BYOS implementation of Key - Value store
+// ************************************************************************
+const trustedBiddingSignalStore = new KeyValueStore([
+ ...BIDDING_SIGNALS_DEFAULT,
+ ...BIDDING_SIGNALS_DEALS,
+]);
+
+// ************************************************************************
+// HTTP handlers
+// ************************************************************************
+/** Simplified BYOS implementation for Key-Value Service. */
+BiddingSignalsRouter.get(
+ '/bidding-signal.json',
+ async (req: Request, res: Response) => {
+ const publisher = req.query.hostname;
+ const queryKeys = req.query.keys?.toString().split(',');
+ const signalsFromKeyValueStore = trustedBiddingSignalStore.getMultiple(
+ queryKeys!,
+ );
+ // Return perInterestGroupData for requested interes groups.
+ const interestGroupNames = req.query
+ .interestGroupNames!.toString()
+ .split(',');
+ const perInterestGroupData: {[key: string]: any} = {};
+ for (const name of interestGroupNames) {
+ perInterestGroupData[name] = {
+ 'priorityVector': {
+ 'signal1': 100,
+ 'signal2': 200,
+ },
+ // Force an interest group update.
+ 'updateIfOlderThanMs': 1,
+ };
+ }
+ const biddingSignals = {
+ keys: {...signalsFromKeyValueStore},
+ perInterestGroupData,
+ };
+ console.log('Returning bidding signals: ', {
+ url: req.originalUrl,
+ publisher,
+ queryKeys,
+ biddingSignals,
+ });
+ res.setHeader('X-Allow-FLEDGE', 'true');
+ res.setHeader('X-fledge-bidding-signals-format-version', '2');
+ res.json(biddingSignals);
+ },
+);
+
+// ************************************************************************
+// HTTP endpoints used for demonstration purposes
+// ************************************************************************
+/** Adds values in query parameters to Key Value Store. */
+BiddingSignalsRouter.get(
+ '/set-bidding-signal.json',
+ async (req: Request, res: Response) => {
+ console.log('Setting bidding signals', {...req.query});
+ for (const key of Object.keys(req.query)) {
+ trustedBiddingSignalStore.set(key, req.query[key]?.toString());
+ }
+ res.sendStatus(200);
+ },
+);
+
+/** Rewrites the default values in the key value store. */
+BiddingSignalsRouter.get(
+ '/reset-scoring-signal.json',
+ async (req: Request, res: Response) => {
+ trustedBiddingSignalStore.rewriteDefaults();
+ res.status(200).send(`Rewrote default real-time signals: ${HOSTNAME}`);
+ },
+);
diff --git a/services/ad-tech/src/routes/dsp/buyer-contextual-bidder-router.ts b/services/ad-tech/src/routes/dsp/buyer-contextual-bidder-router.ts
new file mode 100644
index 00000000..44d05542
--- /dev/null
+++ b/services/ad-tech/src/routes/dsp/buyer-contextual-bidder-router.ts
@@ -0,0 +1,95 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {
+ ADVERTISER_CONTEXTUAL,
+ CURRENT_ORIGIN,
+ EXTERNAL_PORT,
+ HOSTNAME,
+ CONTEXTUAL_BID_MAX,
+ CONTEXTUAL_BID_MIN,
+} from '../../lib/constants.js';
+import {AdType} from '../../lib/interest-group-helper.js';
+import {ContextualBidResponse} from '../../lib/contextual-auction-helper.js';
+
+/**
+ * This router is responsible for handling requests related to contextual
+ * auctions as an ad buyer.
+ *
+ * Path: /dsp/contextual-bid/
+ */
+export const BuyerContextualBidderRouter = express.Router();
+
+// ************************************************************************
+// Helper functions
+// ************************************************************************
+/** Returns a random bid price with 2 decimal digits. */
+const getContextualBidPrice = (): string => {
+ const minBid = CONTEXTUAL_BID_MIN;
+ const maxBid = CONTEXTUAL_BID_MAX;
+ const bid = (Math.random() * (maxBid - minBid) + minBid).toFixed(2);
+ return bid;
+};
+
+// ************************************************************************
+// HTTP handlers
+// ************************************************************************
+/** Places a bid for the contextual auction. */
+BuyerContextualBidderRouter.get('/', async (req: Request, res: Response) => {
+ // Generate a new auction ID if missing in request.
+ const auctionId =
+ req.query.auctionId?.toString() || `DSP-${crypto.randomUUID()}`;
+ const adType = req.query.adType?.toString().toUpperCase() || '';
+ if (AdType.VIDEO === adType) {
+ // Don't place contextual bids for video ads request.
+ const bidResponse: ContextualBidResponse = {
+ bidderOrigin: CURRENT_ORIGIN,
+ bidderHost: HOSTNAME,
+ auctionId,
+ bid: '0.0',
+ buyerSignals: {
+ contextualBid: '0.0',
+ ...req.query,
+ },
+ };
+ console.log('Responding to contextual video ad request', {bidResponse});
+ res.json(bidResponse);
+ return;
+ }
+ // Assemble render URL query parameters.
+ const renderUrlQuery = `advertiser=${ADVERTISER_CONTEXTUAL}&auctionId=${auctionId}`;
+ const renderURL = new URL(
+ `https://${HOSTNAME}:${EXTERNAL_PORT}/ads/contextual-ads?${renderUrlQuery}`,
+ ).toString();
+ const bid = getContextualBidPrice();
+ /** Return contextual bid with buyer signals. */
+ const bidResponse: ContextualBidResponse = {
+ bidderOrigin: CURRENT_ORIGIN,
+ bidderHost: HOSTNAME,
+ auctionId,
+ bid,
+ renderURL,
+ buyerSignals: {
+ auctionId,
+ buyerHost: HOSTNAME,
+ buyerOrigin: CURRENT_ORIGIN,
+ contextualBid: bid,
+ contextualRenderURL: renderURL,
+ contextualAdvertiser: ADVERTISER_CONTEXTUAL,
+ ...req.query,
+ },
+ };
+ console.log('Responding to contextual ad request', {bidResponse});
+ res.json(bidResponse);
+});
diff --git a/services/ad-tech/src/routes/dsp/buyer-router.ts b/services/ad-tech/src/routes/dsp/buyer-router.ts
new file mode 100644
index 00000000..34a621ff
--- /dev/null
+++ b/services/ad-tech/src/routes/dsp/buyer-router.ts
@@ -0,0 +1,128 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {HOSTNAME} from '../../lib/constants.js';
+import {getTemplateVariables} from '../../lib/common-utils.js';
+import {
+ getInterestGroup,
+ TargetingContext,
+} from '../../lib/interest-group-helper.js';
+
+/**
+ * This is the main ad buyer router and is responsible for a variety of
+ * requests made at the top-level path: /dsp. This includes retrieving
+ * iframes to include and the interest group to join on advertiser pages.
+ *
+ * Path: /dsp/
+ */
+export const BuyerRouter = express.Router();
+
+// ************************************************************************
+// HTTP handlers
+// ************************************************************************
+/** Iframe document used as context to join interest group. */
+BuyerRouter.get(
+ '/dsp-advertiser-iframe.html',
+ async (req: Request, res: Response) => {
+ res.render(
+ 'dsp/dsp-advertiser-iframe',
+ getTemplateVariables('Join Ad Interest Group'),
+ );
+ },
+);
+
+/** Returns the interest group to join on an advertiser page. */
+BuyerRouter.get('/interest-group.json', async (req: Request, res: Response) => {
+ const targetingContext = assembleTargetingContext(req.query);
+ res.json(getInterestGroup(targetingContext));
+});
+
+/** Returns the updated interest group, usually daily, may be overridden. */
+BuyerRouter.get(
+ '/interest-group-update.json',
+ async (req: Request, res: Response) => {
+ const targetingContext = assembleTargetingContext(req.query);
+ targetingContext.isUpdateRequest = true;
+ res.json(getInterestGroup(targetingContext));
+ },
+);
+
+/** Iframe document used as context to test Private Aggregation. */
+BuyerRouter.get(
+ '/test-private-aggregation.html',
+ async (req: Request, res: Response) => {
+ const bucket = req.query.bucket;
+ const cloudEnv = req.query.cloudEnv;
+ console.log(`${bucket}, ${cloudEnv}`);
+ res.render('dsp/test-private-aggregation', {
+ bucket: bucket,
+ cloudEnv: cloudEnv,
+ });
+ },
+);
+
+const KNOWN_TARGETING_CONTEXT_KEYS = [
+ 'advertiser',
+ 'usecase',
+ 'itemId',
+ 'biddingSignalKeys',
+];
+/** Assembles the targeting context from query parameters. */
+const assembleTargetingContext = (query: any): TargetingContext => {
+ const {advertiser, usecase, itemId, biddingSignalKeys} = query;
+ const targetingContext: TargetingContext = {
+ advertiser: advertiser?.toString() || HOSTNAME!, // Default to current host
+ usecase: usecase?.toString() || 'default',
+ itemId: itemId?.toString() || '',
+ isUpdateRequest: false,
+ };
+ targetingContext.biddingSignalKeys = [];
+ if (biddingSignalKeys) {
+ if (Array.isArray(biddingSignalKeys)) {
+ targetingContext.biddingSignalKeys.push(
+ ...biddingSignalKeys.map((key) => key.toString()),
+ );
+ } else {
+ targetingContext.biddingSignalKeys.push(
+ biddingSignalKeys.toString().split(','),
+ );
+ }
+ }
+ targetingContext.additionalContext = {};
+ for (const [key, value] of Object.entries(query)) {
+ if (KNOWN_TARGETING_CONTEXT_KEYS.includes(key)) {
+ continue;
+ }
+ if (value) {
+ if (Array.isArray(value)) {
+ targetingContext.additionalContext[key.toString()] = value.map(
+ (value) => value.toString(),
+ );
+ } else {
+ targetingContext.additionalContext[key.toString()] = [
+ ...value.toString().split(','),
+ ];
+ }
+ }
+ }
+ return targetingContext;
+};
+
+/** Returns the updated interest group, usually daily, may be overridden. */
+BuyerRouter.get('/mta-conversion.html', async (req: Request, res: Response) => {
+ const campaignId = 1234;
+ const purchaseValue = req.query.purchaseValue;
+ console.log(`Campaign Id: ${campaignId}, Purchase Value: ${purchaseValue}`);
+ res.render('dsp/mta-conversion.ejs', {campaignId, purchaseValue});
+});
diff --git a/services/ad-tech/src/routes/ssp/scoring-signals-router.ts b/services/ad-tech/src/routes/ssp/scoring-signals-router.ts
new file mode 100644
index 00000000..0d9a0b73
--- /dev/null
+++ b/services/ad-tech/src/routes/ssp/scoring-signals-router.ts
@@ -0,0 +1,138 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {
+ BUYER_HOSTS_TO_INTEGRATE_BY_SELLER_HOST,
+ EXTERNAL_PORT,
+ HOSTNAME,
+ KNOWN_SHOP_ITEM_TAGS_BY_ID,
+ MACRO_DISPLAY_RENDER_URL_AD_SIZE,
+ SHOP_HOST,
+ TRAVEL_HOST,
+} from '../../lib/constants.js';
+import {KeyValueStore} from '../../controllers/key-value-store.js';
+
+/**
+ * This router is responsible for handling requests to retrieve realtime
+ * scoring signals for on-device Protected Audience auctions. In that, this is
+ * a simplified Bring-Your-Own-Server (BYOS) implementation of the Key - Value
+ * Server for ad sellers.
+ *
+ * Path: /ssp/realtime-signals/
+ */
+export const ScoringSignalsRouter = express.Router();
+
+// ****************************************************************************
+// BYOS implementation of Key - Value store
+// ****************************************************************************
+/** Intializes scoring signals for key value store. */
+const getDefaultScoringSignals = (): string[][] => {
+ const buyerHostsToIntegrate = BUYER_HOSTS_TO_INTEGRATE_BY_SELLER_HOST.get(
+ HOSTNAME!,
+ );
+ if (!buyerHostsToIntegrate) {
+ console.log('No buyers to integrate -- expected for buyers themselves');
+ return [];
+ }
+ const knownAds: string[][] = [];
+ // Ads from Travel advertiser
+ for (const dspHost of buyerHostsToIntegrate) {
+ knownAds.push([
+ new URL(
+ `https://${dspHost}:${EXTERNAL_PORT}/ads/display-ads?advertiser=${TRAVEL_HOST}&${MACRO_DISPLAY_RENDER_URL_AD_SIZE}`,
+ ).toString(),
+ JSON.stringify({
+ tags: ['travel'],
+ }),
+ ]);
+ }
+ // Ads from Shop advertiser
+ for (const [key, value] of Object.entries(KNOWN_SHOP_ITEM_TAGS_BY_ID)) {
+ for (const dspHost of buyerHostsToIntegrate) {
+ knownAds.push([
+ new URL(
+ `https://${dspHost}:${EXTERNAL_PORT}/ads/display-ads?advertiser=${SHOP_HOST}&itemId=${key}&${MACRO_DISPLAY_RENDER_URL_AD_SIZE}`,
+ ).toString(),
+ JSON.stringify({
+ tags: value,
+ }),
+ ]);
+ }
+ }
+ return knownAds;
+};
+
+/** BYOS implementation of seller key value store. */
+const trustedScoringSignalsStore = new KeyValueStore(
+ getDefaultScoringSignals(),
+);
+
+// ****************************************************************************
+// HTTP handlers
+// ****************************************************************************
+/** Simplified BYOS implementation for Key-Value Service. */
+ScoringSignalsRouter.get(
+ '/scoring-signal.json',
+ async (req: Request, res: Response) => {
+ // TODO: Partition KV keys by publisher.
+ const publisher = req.query.hostname;
+ const queryRenderUrls = req.query.renderUrls?.toString().split(',') || [];
+ const renderUrlMetadata =
+ trustedScoringSignalsStore.getMultiple(queryRenderUrls);
+ const queryAdAcomponentRenderUrls =
+ req.query.adComponentRenderUrls?.toString().split(',') || [];
+ const adComponentRenderUrlMetadata = trustedScoringSignalsStore.getMultiple(
+ queryAdAcomponentRenderUrls,
+ );
+ console.log(
+ 'KV BYOS querying',
+ {queryRenderUrls, queryAdAcomponentRenderUrls},
+ 'for',
+ {publisher},
+ );
+ const scoringSignals = {
+ renderURLs: {...renderUrlMetadata},
+ adComponentRenderURLs: {...adComponentRenderUrlMetadata},
+ };
+ res.setHeader('X-Allow-FLEDGE', 'true');
+ // res.setHeader('X-fledge-bidding-signals-format-version', '2');
+ console.log('Returning trusted scoring signals: ', {scoringSignals});
+ res.json(scoringSignals);
+ },
+);
+
+// ************************************************************************
+// HTTP endpoints used for demonstration purposes
+// ************************************************************************
+/** Adds values in query parameters to Key Value Store. */
+ScoringSignalsRouter.get(
+ '/set-scoring-signal.json',
+ async (req: Request, res: Response) => {
+ console.log('Setting scoring signals', {...req.query});
+ for (const key of Object.keys(req.query)) {
+ trustedScoringSignalsStore.set(key, req.query[key]?.toString());
+ }
+ res.sendStatus(200);
+ },
+);
+
+/** Rewrites the default values in the key value store. */
+ScoringSignalsRouter.get(
+ '/reset-scoring-signal.json',
+ async (req: Request, res: Response) => {
+ console.log('');
+ trustedScoringSignalsStore.rewriteDefaults();
+ res.status(200).send(`Rewrote default real-time signals: ${HOSTNAME}`);
+ },
+);
diff --git a/services/ad-tech/src/routes/ssp/seller-contextual-bidder-router.ts b/services/ad-tech/src/routes/ssp/seller-contextual-bidder-router.ts
new file mode 100644
index 00000000..e2c2f367
--- /dev/null
+++ b/services/ad-tech/src/routes/ssp/seller-contextual-bidder-router.ts
@@ -0,0 +1,98 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {
+ ContextualBidResponse,
+ getContextualBids,
+} from '../../lib/contextual-auction-helper.js';
+import {constructAuctionConfig} from '../../lib/auction-config-helper.js';
+import {
+ HOSTNAME,
+ CURRENT_ORIGIN,
+ BUYER_HOSTS_TO_INTEGRATE_BY_SELLER_HOST,
+} from '../../lib/constants.js';
+
+/**
+ * This router is responsible for handling contextual bid requests as an ad
+ * seller. When a seller receives a contextual bid request, it forwards this
+ * bid request to a set of ad buyers. These buyers respond with a bid and buyer
+ * signals to include in Protected Audience auctions. The seller picks the
+ * winning contextual bid, collates all buyer signals to responds to the
+ * original bid request with the winning contextual bid and the component
+ * auction configuration to use with Protected Audience.
+ *
+ * Path: /ssp/contextual-bid/
+ */
+export const SellerContextualBidderRouter = express.Router();
+
+// ************************************************************************
+// HTTP handlers
+// ************************************************************************
+/** Returns the winning contextual ad and auction config for PAAPI. */
+SellerContextualBidderRouter.get('/', async (req: Request, res: Response) => {
+ // Collect signals from request context.
+ const auctionSignals: {[key: string]: string} = {};
+ const sellerSignals: {[key: string]: string} = {};
+ for (const key of Object.keys(req.query)) {
+ if (key.startsWith('sellerSignal')) {
+ // Example key in incoming HTTP request: "sellerSignalExcludeProductTag".
+ let sellerSignalKey = key.substring('sellerSignal'.length);
+ // Convert "ExcludeProductTag" to "excludeProductTag"
+ sellerSignalKey =
+ sellerSignalKey.charAt(0).toLowerCase() + sellerSignalKey.substring(1);
+ sellerSignals[sellerSignalKey] = req.query[key]?.toString() || '';
+ } else {
+ auctionSignals[key] = req.query[key]?.toString() || '';
+ }
+ }
+ if (!auctionSignals['auctionId']) {
+ // Add an auction ID if missing in request.
+ // E.g. of auction ID: 'SSP-32e7f33f-a7da-4ea9-af01-63e17da48ff8'
+ auctionSignals['auctionId'] = `SSP-${crypto.randomUUID()}`;
+ }
+ // Run server-side contextual auction.
+ const contextualBids = await getContextualBids(
+ /* bidderHosts= */ BUYER_HOSTS_TO_INTEGRATE_BY_SELLER_HOST.get(HOSTNAME!)!,
+ /* signals= */ auctionSignals,
+ );
+ const [winningContextualBid] = contextualBids
+ .filter((bid) => Number(bid.bid) > 0)
+ .sort((bid1, bid2) => Number(bid2.bid!) - Number(bid1.bid!));
+ console.log('Winning contextual bid', {winningContextualBid});
+ // Collect buyer signals from contextual bids.
+ const perBuyerSignals: {[key: string]: any} = {};
+ for (const contextualBid of contextualBids) {
+ if (contextualBid.buyerSignals) {
+ perBuyerSignals[contextualBid.bidderOrigin!] = contextualBid.buyerSignals;
+ }
+ }
+ const response: ContextualBidResponse = {
+ bidderOrigin: CURRENT_ORIGIN,
+ bidderHost: HOSTNAME,
+ buyerOrigin: winningContextualBid?.bidderOrigin,
+ buyerHost: winningContextualBid?.bidderHost,
+ auctionId: auctionSignals['auctionId'],
+ bid: winningContextualBid?.bid,
+ renderURL: winningContextualBid?.renderURL,
+ componentAuctionConfig: constructAuctionConfig({
+ useCase: req.query.useCase?.toString(),
+ isFencedFrame: req.query.isFencedFrame?.toString(),
+ auctionSignals: auctionSignals,
+ sellerSignals: {winningContextualBid, ...sellerSignals},
+ perBuyerSignals,
+ }),
+ };
+ console.log('Responding to contextual bid request', {response});
+ res.json(response);
+});
diff --git a/services/ad-tech/src/routes/ssp/seller-router.ts b/services/ad-tech/src/routes/ssp/seller-router.ts
new file mode 100644
index 00000000..00bd135a
--- /dev/null
+++ b/services/ad-tech/src/routes/ssp/seller-router.ts
@@ -0,0 +1,80 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {EXTERNAL_PORT, HOSTNAME} from '../../lib/constants.js';
+import {constructAuctionConfig} from '../../lib/auction-config-helper.js';
+
+/**
+ * This is the main Seller router and is responsible for handling a variety of
+ * requests made at the top-level path: /ssp. This includes retrieving
+ * iframes that deliver ads, auction configurations, and the wrapped VAST XML
+ * for video ads.
+ *
+ * Path: /ssp/
+ */
+export const SellerRouter = express.Router();
+
+// TODO: Rename to run-single-seller-ad-auction after unified branch is merged.
+/** Iframe document used as context to run single-seller PAAPI auction. */
+SellerRouter.get(
+ '/run-ad-auction.html',
+ async (req: Request, res: Response) => {
+ res.render('ssp/run-ad-auction');
+ },
+);
+
+/** Iframe document used as context to run multi-seller PAAPI auction. */
+SellerRouter.get(
+ '/run-sequential-ad-auction.html',
+ async (req: Request, res: Response) => {
+ res.render('ssp/run-sequential-ad-auction');
+ },
+);
+
+/** Returns the PAAPI auction config. */
+SellerRouter.get(
+ '/auction-config.json',
+ async (req: Request, res: Response) => {
+ const signals: {[key: string]: string} = {};
+ for (const key of Object.keys(req.query)) {
+ signals[key] = req.query[key]?.toString() || '';
+ }
+ const auctionConfig = constructAuctionConfig({
+ useCase: req.query.useCase?.toString(),
+ isFencedFrame: req.query.isFencedFrame?.toString(),
+ auctionSignals: signals,
+ });
+ console.log('Returning auction config: ', {auctionConfig});
+ res.json(auctionConfig);
+ },
+);
+
+/** Returns the finalized VAST XML to deliver video ads with PAAPI. */
+SellerRouter.get('/vast.xml', async (req: Request, res: Response) => {
+ const dspVast = decodeURIComponent(req.query.dspVast?.toString() || '');
+ const auctionId =
+ req.query.auctionId?.toString() || `SSP-${crypto.randomUUID()}`;
+ const advertiser = req.query.advertiser?.toString() || HOSTNAME;
+ /**
+ * TODO: Consider using additional video ad types.
+ * https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/tags
+ */
+ res.type('application/xml').render('ssp/vast-preroll', {
+ HOSTNAME,
+ EXTERNAL_PORT,
+ AUCTION_ID: auctionId,
+ DSP_VAST: dspVast,
+ ADVERTISER_HOST: advertiser,
+ });
+});
diff --git a/services/ad-tech/src/routes/well-known/well-known-attribution-reporting-router.ts b/services/ad-tech/src/routes/well-known/well-known-attribution-reporting-router.ts
new file mode 100644
index 00000000..2b6bf797
--- /dev/null
+++ b/services/ad-tech/src/routes/well-known/well-known-attribution-reporting-router.ts
@@ -0,0 +1,129 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import cbor from 'cbor';
+import express, {Request, Response} from 'express';
+import {ReportStore, ReportCategory} from '../../controllers/report-store.js';
+import {decodeBucket} from '../../lib/arapi.js';
+
+/**
+ * This router is responsible for handling the well-known endpoints for the
+ * Attribution Reporting API. There are two types reports with this API --
+ * (1) event-level reports, and (2) summary reports or aggregate reports. And
+ * for each report type, we may receive regular reports and debug reports.
+ *
+ * Path: /.well-known/attribution-reporting/
+ */
+export const WellKnownAttributionReportingRouter = express.Router();
+
+// ************************************************************************
+// Attribution Reporting: Event-level Reports
+// ************************************************************************
+// Event-level Report: Regular Report
+WellKnownAttributionReportingRouter.post(
+ '/report-event-attribution',
+ async (req: Request, res: Response) => {
+ console.log(
+ '[ARA] Received event-level report on live endpoint: ',
+ req.body,
+ );
+ ReportStore.addReport({
+ category: ReportCategory.ARA_EVENT_LEVEL,
+ timestamp: Date.now().toString(),
+ data: req.body,
+ });
+ res.sendStatus(200);
+ },
+);
+
+// Event-level Report: Debug Report
+WellKnownAttributionReportingRouter.post(
+ '/debug/report-event-attribution',
+ async (req: Request, res: Response) => {
+ console.log(
+ '[ARA] Received event-level report on debug endpoint: ',
+ req.body,
+ );
+ ReportStore.addReport({
+ category: ReportCategory.ARA_EVENT_LEVEL_DEBUG,
+ timestamp: Date.now().toString(),
+ data: req.body,
+ });
+ res.sendStatus(200);
+ },
+);
+
+// ************************************************************************
+// Attribution Reporting: Aggregate Reports
+// ************************************************************************
+// Aggregate Report: Regular Report
+WellKnownAttributionReportingRouter.post(
+ '/report-aggregate-attribution',
+ async (req: Request, res: Response) => {
+ const report = req.body;
+ report.shared_info = JSON.parse(report.shared_info);
+ console.log(
+ '[ARA] Received aggregatable report on live endpoint: ',
+ JSON.stringify(report),
+ );
+ ReportStore.addReport({
+ category: ReportCategory.ARA_AGGREGATE,
+ timestamp: Date.now().toString(),
+ data: report,
+ });
+ res.sendStatus(200);
+ },
+);
+
+// Aggregate Report: Debug Report
+WellKnownAttributionReportingRouter.post(
+ '/debug/report-aggregate-attribution',
+ async (req: Request, res: Response) => {
+ const debugReport = req.body;
+ debugReport.shared_info = JSON.parse(debugReport.shared_info);
+ debugReport.aggregation_service_payloads =
+ debugReport.aggregation_service_payloads.map((e: any) => {
+ const plain = Buffer.from(e.debug_cleartext_payload, 'base64');
+ const debug_cleartext_payload = cbor.decodeAllSync(plain);
+ e.debug_cleartext_payload = debug_cleartext_payload.map(
+ ({data, operation}) => {
+ return {
+ operation,
+ data: data.map(({value, bucket}: any) => {
+ return {
+ value: value.readUInt32BE(0),
+ bucket: decodeBucket(bucket),
+ };
+ }),
+ };
+ },
+ );
+ return e;
+ });
+ console.log(
+ '[ARA] Received aggregatable report on debug endpoint: ',
+ JSON.stringify(debugReport),
+ );
+ // Save to global storage
+ ReportStore.addReport({
+ category: ReportCategory.ARA_AGGREGATE_DEBUG,
+ timestamp: Date.now().toString(),
+ data: debugReport,
+ });
+ res.sendStatus(200);
+ },
+);
+
+// TODO: Implement verbose debug reports for ARA.
+// WellKnownAttributionReportingRouter.post('/debug/verbose',
+// async (req: Request, res: Response) => {});
diff --git a/services/ad-tech/src/routes/well-known/well-known-private-aggregation-router.ts b/services/ad-tech/src/routes/well-known/well-known-private-aggregation-router.ts
new file mode 100644
index 00000000..95d1af66
--- /dev/null
+++ b/services/ad-tech/src/routes/well-known/well-known-private-aggregation-router.ts
@@ -0,0 +1,100 @@
+/*
+ Copyright 2022 Google LLC
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ https://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+import express, {Request, Response} from 'express';
+import {ReportStore, ReportCategory} from '../../controllers/report-store.js';
+
+/**
+ * This router is responsible for handling the well-known endpoints for the
+ * Private Aggregation API. There are two ways to generate reports with the
+ * Private Aggregation API -- (1) via Shared Storage, and (2) via Protected
+ * Audience. And with each way, we may receive regular reports and debug
+ * reports.
+ *
+ * Path: /.well-known/private-aggregation/
+ */
+export const WellKnownPrivateAggregationRouter = express.Router();
+
+// ************************************************************************
+// Private Aggregation with Shared Storage
+// ************************************************************************
+// Shared Storage: Regular report
+WellKnownPrivateAggregationRouter.post(
+ '/report-shared-storage',
+ async (req: Request, res: Response) => {
+ console.log(
+ '[pAgg+SS] Received aggregatable report on live endpoint: ',
+ req.body,
+ );
+ ReportStore.addReport({
+ category: ReportCategory.PAGG_VIA_SS,
+ timestamp: Date.now().toString(),
+ data: req.body,
+ });
+ res.sendStatus(200);
+ },
+);
+
+// Shared Storage: Debug report
+WellKnownPrivateAggregationRouter.post(
+ '/debug/report-shared-storage',
+ async (req: Request, res: Response) => {
+ console.log(
+ '[pAgg+SS] Received aggregatable report on debug endpoint: ',
+ req.body,
+ );
+ ReportStore.addReport({
+ category: ReportCategory.PAGG_VIA_SS_DEBUG,
+ timestamp: Date.now().toString(),
+ data: req.body,
+ });
+ res.sendStatus(200);
+ },
+);
+
+// ************************************************************************
+// Private Aggregation with Protected Audience
+// ************************************************************************
+// Protected Audience: Regular report
+WellKnownPrivateAggregationRouter.post(
+ '/report-protected-audience',
+ async (req: Request, res: Response) => {
+ console.log(
+ '[pAgg+SS] Received aggregatable report on live endpoint: ',
+ req.body,
+ );
+ ReportStore.addReport({
+ category: ReportCategory.PAGG_VIA_PAAPI,
+ timestamp: Date.now().toString(),
+ data: req.body,
+ });
+ res.sendStatus(200);
+ },
+);
+
+// Protected Audience: Debug report
+WellKnownPrivateAggregationRouter.post(
+ '/debug/report-protected-audience',
+ async (req: Request, res: Response) => {
+ console.log(
+ '[pAgg+SS] Received aggregatable report on debug endpoint: ',
+ req.body,
+ );
+ ReportStore.addReport({
+ category: ReportCategory.PAGG_VIA_PAAPI_DEBUG,
+ timestamp: Date.now().toString(),
+ data: req.body,
+ });
+ res.sendStatus(200);
+ },
+);
diff --git a/services/ad-tech/src/views/contextual-ad-frame.ejs b/services/ad-tech/src/views/contextual-ad-frame.ejs
new file mode 100644
index 00000000..1582de13
--- /dev/null
+++ b/services/ad-tech/src/views/contextual-ad-frame.ejs
@@ -0,0 +1,63 @@
+<%/* This is used in fenced-frames to deliver ads. */%>
+
+
+
+
+
+
+ <%= TITLE %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/ad-tech/src/views/display-ad-frame.ejs b/services/ad-tech/src/views/display-ad-frame.ejs
new file mode 100644
index 00000000..c74ea159
--- /dev/null
+++ b/services/ad-tech/src/views/display-ad-frame.ejs
@@ -0,0 +1,61 @@
+<%/* This is used in fenced-frames to deliver ads. */%>
+
+
+
+
+
+
+ <%= TITLE %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/services/ad-tech/src/views/dsp/dsp-advertiser-iframe.ejs b/services/ad-tech/src/views/dsp/dsp-advertiser-iframe.ejs
new file mode 100644
index 00000000..1eef1f3b
--- /dev/null
+++ b/services/ad-tech/src/views/dsp/dsp-advertiser-iframe.ejs
@@ -0,0 +1,18 @@
+<%/* This is used in buyer iframes to join an interest group. */%>
+
+
+
+
+
+
+
+
+ <%/* Script to add user to an interest group. */%>
+
+
+
+
diff --git a/services/ad-tech/src/views/dsp/mta-conversion.ejs b/services/ad-tech/src/views/dsp/mta-conversion.ejs
new file mode 100644
index 00000000..0b26eb30
--- /dev/null
+++ b/services/ad-tech/src/views/dsp/mta-conversion.ejs
@@ -0,0 +1,5 @@
+
+
+