From 057a57406d90471ee569fb330b134cda9f83798c Mon Sep 17 00:00:00 2001 From: Wesley Dawson Date: Mon, 17 Oct 2022 14:43:50 -0700 Subject: [PATCH 1/2] Delete etl-graph job --- .circleci/config.yml | 27 - jobs/etl-graph/.dockerignore | 9 - jobs/etl-graph/.env.template | 3 - jobs/etl-graph/.gitignore | 11 - jobs/etl-graph/Dockerfile | 20 - jobs/etl-graph/NOTES.md | 294 --- jobs/etl-graph/README.md | 66 - jobs/etl-graph/ci_job.yaml | 12 - jobs/etl-graph/ci_workflow.yaml | 13 - jobs/etl-graph/docker-compose.yml | 19 - jobs/etl-graph/etl-graph/__init__.py | 0 jobs/etl-graph/etl-graph/__main__.py | 6 - jobs/etl-graph/etl-graph/commands.py | 137 - jobs/etl-graph/etl-graph/config.py | 4 - jobs/etl-graph/etl-graph/crawler.py | 117 - .../etl-graph/resources/query_log_edges.sql | 93 - .../etl-graph/resources/query_log_nodes.sql | 63 - .../etl-graph/resources/query_logs.sql | 67 - jobs/etl-graph/etl-graph/utils.py | 93 - jobs/etl-graph/package-lock.json | 2329 ----------------- jobs/etl-graph/package.json | 32 - jobs/etl-graph/public/index.html | 14 - jobs/etl-graph/requirements.in | 3 - jobs/etl-graph/requirements.txt | 10 - jobs/etl-graph/rollup.config.js | 83 - jobs/etl-graph/screenshot.png | Bin 63970 -> 0 bytes jobs/etl-graph/scripts/deploy-data.sh | 10 - jobs/etl-graph/scripts/deploy-site.sh | 11 - jobs/etl-graph/scripts/scrape.sh | 10 - jobs/etl-graph/src/App.svelte | 19 - jobs/etl-graph/src/components/FrontMatter.svx | 25 - jobs/etl-graph/src/components/Nav.svelte | 22 - jobs/etl-graph/src/components/Network.svelte | 85 - .../etl-graph/src/components/SearchBox.svelte | 64 - jobs/etl-graph/src/components/Summary.svelte | 102 - jobs/etl-graph/src/main.js | 11 - jobs/etl-graph/src/routes/Artifacts.svelte | 26 - jobs/etl-graph/src/routes/Explorer.svelte | 51 - jobs/etl-graph/src/routes/Routes.svelte | 24 - jobs/etl-graph/src/routes/Statistics.svelte | 73 - jobs/etl-graph/src/store.js | 4 - jobs/etl-graph/src/utils.js | 73 - 42 files changed, 4135 deletions(-) delete mode 100644 jobs/etl-graph/.dockerignore delete mode 100644 jobs/etl-graph/.env.template delete mode 100644 jobs/etl-graph/.gitignore delete mode 100644 jobs/etl-graph/Dockerfile delete mode 100644 jobs/etl-graph/NOTES.md delete mode 100644 jobs/etl-graph/README.md delete mode 100644 jobs/etl-graph/ci_job.yaml delete mode 100644 jobs/etl-graph/ci_workflow.yaml delete mode 100644 jobs/etl-graph/docker-compose.yml delete mode 100644 jobs/etl-graph/etl-graph/__init__.py delete mode 100644 jobs/etl-graph/etl-graph/__main__.py delete mode 100644 jobs/etl-graph/etl-graph/commands.py delete mode 100644 jobs/etl-graph/etl-graph/config.py delete mode 100644 jobs/etl-graph/etl-graph/crawler.py delete mode 100644 jobs/etl-graph/etl-graph/resources/query_log_edges.sql delete mode 100644 jobs/etl-graph/etl-graph/resources/query_log_nodes.sql delete mode 100644 jobs/etl-graph/etl-graph/resources/query_logs.sql delete mode 100644 jobs/etl-graph/etl-graph/utils.py delete mode 100644 jobs/etl-graph/package-lock.json delete mode 100644 jobs/etl-graph/package.json delete mode 100644 jobs/etl-graph/public/index.html delete mode 100644 jobs/etl-graph/requirements.in delete mode 100644 jobs/etl-graph/requirements.txt delete mode 100644 jobs/etl-graph/rollup.config.js delete mode 100644 jobs/etl-graph/screenshot.png delete mode 100755 jobs/etl-graph/scripts/deploy-data.sh delete mode 100755 jobs/etl-graph/scripts/deploy-site.sh delete mode 100755 jobs/etl-graph/scripts/scrape.sh delete mode 100644 jobs/etl-graph/src/App.svelte delete mode 100644 jobs/etl-graph/src/components/FrontMatter.svx delete mode 100644 jobs/etl-graph/src/components/Nav.svelte delete mode 100644 jobs/etl-graph/src/components/Network.svelte delete mode 100644 jobs/etl-graph/src/components/SearchBox.svelte delete mode 100644 jobs/etl-graph/src/components/Summary.svelte delete mode 100644 jobs/etl-graph/src/main.js delete mode 100644 jobs/etl-graph/src/routes/Artifacts.svelte delete mode 100644 jobs/etl-graph/src/routes/Explorer.svelte delete mode 100644 jobs/etl-graph/src/routes/Routes.svelte delete mode 100644 jobs/etl-graph/src/routes/Statistics.svelte delete mode 100644 jobs/etl-graph/src/store.js delete mode 100644 jobs/etl-graph/src/utils.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 75138c43..491a8891 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -81,19 +81,6 @@ jobs: name: Test Code command: docker run app:build pytest --flake8 --black - build-job-etl-graph: - docker: - - image: docker:stable-git - steps: - - checkout - - compare-branch: - pattern: ^jobs/etl-graph/ - - setup_remote_docker: - version: 19.03.13 - - run: - name: Build Docker image - command: docker build -t app:build jobs/etl-graph/ - build-job-example_job: docker: @@ -262,20 +249,6 @@ workflows: jobs: - build-job-desktop-mobile-mau-2020 - job-etl-graph: - jobs: - - build-job-etl-graph - - gcp-gcr/build-and-push-image: - context: data-eng-airflow-gcr - docker-context: jobs/etl-graph/ - path: jobs/etl-graph/ - image: etl-graph_docker_etl - requires: - - build-job-etl-graph - filters: - branches: - only: main - job-example_job: jobs: diff --git a/jobs/etl-graph/.dockerignore b/jobs/etl-graph/.dockerignore deleted file mode 100644 index 915c54cd..00000000 --- a/jobs/etl-graph/.dockerignore +++ /dev/null @@ -1,9 +0,0 @@ -data/ -*.pyc -__pycache__/ -.vscode -venv/ - -node_modules -public/build/ -.DS_Store diff --git a/jobs/etl-graph/.env.template b/jobs/etl-graph/.env.template deleted file mode 100644 index b61a34f3..00000000 --- a/jobs/etl-graph/.env.template +++ /dev/null @@ -1,3 +0,0 @@ -CLOUDSDK_CONFIG=~/.config/gcloud -# See https://github.com/mozilla-services/data-sandbox-terraform/tree/master/projects/etl-graph -CLOUDSDK_CORE_PROJECT=etl-graph diff --git a/jobs/etl-graph/.gitignore b/jobs/etl-graph/.gitignore deleted file mode 100644 index 4ee05360..00000000 --- a/jobs/etl-graph/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -data/ -*.pyc -__pycache__/ -.vscode -venv/ - -/node_modules/ -/public/build/ -.DS_Store - -.env diff --git a/jobs/etl-graph/Dockerfile b/jobs/etl-graph/Dockerfile deleted file mode 100644 index 231ee99e..00000000 --- a/jobs/etl-graph/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM gcr.io/google.com/cloudsdktool/cloud-sdk - -RUN apt-get update && apt-get -y install npm - -# upgrade node to the latest version -RUN npm install -g n && n stable - -WORKDIR /app - -# check if dependencies change, otherwise reuse layers -COPY requirements.txt . -RUN pip3 install -r requirements.txt -COPY package.json . -COPY package-lock.json . -RUN npm install - -ADD . . -RUN npm run build - -CMD scripts/scrape.sh && scripts/deploy-data.sh diff --git a/jobs/etl-graph/NOTES.md b/jobs/etl-graph/NOTES.md deleted file mode 100644 index 59859e72..00000000 --- a/jobs/etl-graph/NOTES.md +++ /dev/null @@ -1,294 +0,0 @@ -# Summer 2020 All Hands - Development notes - -_Written 2020-06-18_ - -Let's build a network of the relationships between tables in BigQuery. The -catalog of datasets and tables keeps growing, but our understanding of the -relationships between them is opaque. The goal is to explore the different ways -that table relationships can be surfaced. - -In this project, we generate an an index of tables that is consumed by graph -visualization software. The methods for creating this dataset can help inform or -automate the discover of relationships between tables. - -## Resolving Views - -We start by exploring the JSON output from the various `bq` commands. Running -`bq ls` can enumerate both the datasets and tables within a project. - -```bash -# Dump a listing of the telemetry_derived, which contains results derived from the telemetry dataset -bq ls --format=json moz-fx-data-shared-prod:telemetry_derived | jq '.' > data/telemetry_derived.listing.json - -# Lets take a look at one of the tables. -cat data/telemetry_derived.listing.json | jq '.[] | select(.tableReference.tableId=="core_clients_daily_v1")' -{ - "kind": "bigquery#table", - "creationTime": "1574172370749", - "tableReference": { - "projectId": "moz-fx-data-shared-prod", - "tableId": "core_clients_daily_v1", - "datasetId": "telemetry_derived" - }, - "timePartitioning": { - "field": "submission_date", - "type": "DAY" - }, - "type": "TABLE", - "id": "moz-fx-data-shared-prod:telemetry_derived.core_clients_daily_v1" -} - -# We can query a single partition using the --dry_run flag. While we get the schema, we dont know -# what query was run to derive it. -bq query --dry_run --use_legacy_sql=false --format=json \ - 'select * from `moz-fx-data-shared-prod`.telemetry_derived.core_clients_daily_v1 - where submission_date = date_sub(current_date, interval 1 day)' | jq - -# ...but maybe we can dereference a view? -cat data/telemetry_derived.listing.json | jq '[.[] | select(.type=="VIEW")][0]' -{ - "kind": "bigquery#table", - "creationTime": "1592075573176", - "tableReference": { - "projectId": "moz-fx-data-shared-prod", - "tableId": "core_live", - "datasetId": "telemetry_derived" - }, - "type": "VIEW", - "id": "moz-fx-data-shared-prod:telemetry_derived.core_live", - "view": { - "useLegacySql": false - } -} - -bq show --format=json moz-fx-data-shared-prod:telemetry_derived.core_live -``` - -The JSON response from both `bq ls` and `bq query --dry_run` gives us all of the -known tables and views in any project that we have access to. Instead of using -the `bq ls` listing, it's more efficient to use -[`{dataset}.INFORMATION_SCHEMA.TABLES` and `{dataset}.INFORMATION_SCHEMA.VIEWS`](https://cloud.google.com/bigquery/docs/view-metadata) -directly to enumerate tables. - -```bash -bq query --use_legacy_sql=false 'select * from `moz-fx-data-shared-prod`.telemetry_derived.INFORMATION_SCHEMA.VIEWS limit 3' -+-------------------------+-------------------+-------------------------+-------------------------------------------------------------------------------+--------------+------------------+ -| table_catalog | table_schema | table_name | view_definition | check_option | use_standard_sql | -+-------------------------+-------------------+-------------------------+-------------------------------------------------------------------------------+--------------+------------------+ -| moz-fx-data-shared-prod | telemetry_derived | ssl_ratios_v1 | SELECT * FROM `mozilla-public-data.telemetry_derived.ssl_ratios_v1` | NULL | YES | -| moz-fx-data-shared-prod | telemetry_derived | italy_covid19_outage_v1 | SELECT * FROM `mozilla-public-data.telemetry_derived.italy_covid19_outage_v1` | NULL | YES | -| moz-fx-data-shared-prod | telemetry_derived | origin_content_blocking | select * from `moz-fx-prio-admin-prod-098j.telemetry.origin_content_blocking` | NULL | YES | -+-------------------------+-------------------+-------------------------+-------------------------------------------------------------------------------+--------------+------------------+ -``` - -We'll dry-run each of these to obtain a dereference of the views. Here's an -example response for reference. - -```bash -bq query --format=json --use_legacy_sql=false \ - 'select * from `moz-fx-data-shared-prod`.telemetry_derived.INFORMATION_SCHEMA.VIEWS' \ - | jq > data/telemetry_derived.view_listing.json - -bq query --dry_run --use_legacy_sql=false --format=json \ - $(cat data/telemetry_derived.view_listing.json | jq -r '.[0].view_definition') \ - | jq -{ - "status": { - "state": "DONE" - }, - "kind": "bigquery#job", - "statistics": { - "query": { - "totalBytesProcessedAccuracy": "PRECISE", - "statementType": "SELECT", - "totalBytesBilled": "0", - "totalBytesProcessed": "33089028", - "cacheHit": false, - "referencedTables": [ - { - "projectId": "mozilla-public-data", - "tableId": "ssl_ratios_v1", - "datasetId": "telemetry_derived" - } - ], - "schema": { ... }, - "creationTime": "1592247616179", - "totalBytesProcessed": "33089028" - }, - "jobReference": { - "projectId": "etl-graph", - "location": "US" - }, - "etag": "0R22JEj0sN6llLaF89uLYQ==", - "selfLink": "https://bigquery.googleapis.com/bigquery/v2/projects/etl-graph/jobs/?location=US", - "configuration": { - "query": { - "priority": "INTERACTIVE", - "query": "SELECT * FROM `mozilla-public-data.telemetry_derived.ssl_ratios_v1`", - "writeDisposition": "WRITE_TRUNCATE", - "destinationTable": { - "projectId": "etl-graph", - "tableId": "anon68f47445ca00f2c4ff0b48b76f19d719765dc279", - "datasetId": "_03669b2b0ddaee49592cf590b62f5694460e8d68" - }, - "useLegacySql": false - }, - "dryRun": true, - "jobType": "QUERY" - }, - "id": "etl-graph:US.", - "user_email": "amiyaguchi@mozilla.com" -} -``` - -Here, we only care about `.query.statistics.referencedTables`, which we can use -as edges in our graph. Now the question is what to do when we run into a table -glob. - -```bash -bq query --dry_run --format=json --use_legacy_sql=false \ - 'select submission_timestamp from `moz-fx-data-shared-prod.payload_bytes_decoded.telemetry_*` - where date(submission_timestamp) = date_sub(current_date, interval 1 day)' \ - | jq '.statistics.query.referencedTables' -[ - { - "projectId": "moz-fx-data-shared-prod", - "tableId": "telemetry_*", - "datasetId": "payload_bytes_decoded" - } -] -``` - -In order to fully realize edges between views and tables, we'll have to -enumerate all of the nodes and do the globbing ourselves. Thankfully the -globbing rules are straightforward -- star globs may only be used for the table -suffix. - -This problem is tricky because we do not have information about the underylying -tables. They may require partition filters. We try various combinations of -queries to over come this. Here are some example errors. - -```bash -bq query --use_legacy_sql=false --dry_run --format=json 'select * from `moz-fx-data-shared-prod`.mozza.event' -Error in query string: Cannot query over table 'moz-fx-data-shared-prod.mozza_stable.event_v1' without a filter over column(s) 'submission_timestamp' that can be used for partition elimination - -bq query --use_legacy_sql=false --dry_run --format=json 'select * from `moz-fx-data-shared-prod`.mozza.event where submission_date = date_sub(current_date, interval 1 day)' -Error in query string: Unrecognized name: submission_date at [1:59] -``` - -## Resolving Queries - -Now that we have most of the tables and views resolved, we can start to look at -the relationships between them. One way to this is to assume -`mozilla/bigquery-etl` as the source. While this approach is feasible, there are -some quirks related to the behavior of backticks being used as substitition in -the shell. - -The approach taken here is to take advantage of bigquery metadata. - -```sql -SELECT - creation_time, - destination_table, - referenced_tables -FROM - `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT -WHERE - error_result IS NULL - AND state="DONE" - -- dont care about destination tables without references at the moment - AND referenced_tables IS NOT NULL - -- filter out queries without a real destination - AND NOT (destination_table.table_id LIKE "anon%" - AND destination_table.dataset_id LIKE "_%") -LIMIT - 100 -``` - -There are a few quirks that need to be resolved to obtain a clean list of edges. -First, we'll remove any of the partition filters (e.g. -`baseline_clients_daily_v1$20200511`). We also take care to remove suffixes -added by the bigquery-spark connector (e.g. -`active_profiles_v1_2020_04_19_80b09a`) Then we'll flatten out this list and -deduplicate any of the edges while retaining the most recent creation date. See -`etl-graph/resources/shared_prod_edgelist.sql` for more details. - -## Generating edges - -Now that we've collected the pre-requisite data from the project, we generate a -JSON and CSV blob that represents the set of edges between tables. The first -column is the destination table of the query, while the second column is the -referenced tables within the query. We merge this with edges from the -derefernced views so we can build a complete picture of the network. - -The resulting CSV file can be imported directly into Gephi. The JSON file can be -manipulated within Python or Javascript with relative easy. - -## Visualization - -The visualization is done within the browser for interactive use. It takes -advantage of `vis-network` which allows for manipulation of the network. There -were a few iterations that were taken on the final structure of the network. The -decision was made to add the qualified dataset name as a node in the network, -since this decreased the number of connected components in the graph. This -overall gives the graph more structure and makes it easy to list the tables -within a dataset. The settings for the visualization have not been tuned very -much, so it does take quite a bit for the network to reach a steady state (if it -does at all). - -The site is an html file that refers to the edges in GCS. The site is hosted in -cloud storage, using protodash to proxy the files behind authentication. -Overall, this approach works great for this visualization. - -## Areas for further exploration - -The current network is built only using table and query information from -`moz-fx-data-shared-prod`. There are several projects that would be useful to -surface, including the public-data dataset and all of the sandbox projects. The -views and tables can be crawled with the current permissions, but there may be -hurdles to get access to `INFORMATION_SCHEMA.JOBS_BY_PROJECT` in other projects -outside of shared-prod. - -There is minor enhancements to be made, such as resolving table globs from -views. This should actually resolve to all of the tables that are actually -referenced. Dry run does not expose this information. - -While trying to crawl queries from within `bigquery-etl`, it was noticably -difficult to `--dry-run` queries within the repository. While the query logs are -useful, being able to map these to the `bigquery-etl` queries would be -beneifical for pointing toward the location where the query can be modified. -Additionally, it is difficult to infer the destination table location from the -`bigquery-etl` repository because the project is not encoded within the path to -the SQL files. It is worth considering refactoring the ETL repository to make -the destination table more obvious and easier to map to the query logs. - -The visualization could be improved on a bit. It is noisy since there are many -edges added for datasets with many tables. One feature that would be useful -would be to dynamically prune the network so you only see a local view of the -parents and dependents of a node. The network looks (and is) complex, so this -would make navigation and responsiveness much better. - -The network currently throws away weights related to the edges. A single table -may point to another table several times because a query is being run on a -schedule as opposed to on demand. The edge could include the count of the times -that it appears, along with the last run time. The network continues to evolve -over time, which can be surfaced by changing attributes in the graph such as the -size of a node or the thickness of its edges. These attributes can also affect -the physics simulation that is used to visualize the network. - -Scheduling the crawler should be straightforward. Serving a single JSON file or -a table in BigQuery would be an ideal output. This could be consumed various -tools. - -## Conclusions - -With the interest in building out tooling to make schemas and table provenance -easier to reason about, there is a clear path to reasoning about relationships -between tables. With -[bug 1646157](https://bugzilla.mozilla.org/show_bug.cgi?id=1646157), we are now -empowered to use the BigQuery query logs to surface this information. One -example application of this network would be to answer the question "how was -this table generated?" We can surface the last query that generated it, as well -as the tables that it references. In a prototype of a schema dictionary, the -table relationship information can provide navigation between tables. An up to -date index of tables could be useful for exploring our evolving datasets. diff --git a/jobs/etl-graph/README.md b/jobs/etl-graph/README.md deleted file mode 100644 index ae22c3b1..00000000 --- a/jobs/etl-graph/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# etl-graph - -Queries and visualization around BigQuery usage. This is published to -https://etl-graph.protosaur.dev. - -![screenshot](screenshot.png) - -## Quickstart - -Scrape the data. - -```bash -# optional: virtualenv -python3 -m venv venv -source venv/bin/activate -pip-compile -pip3 install -r requirements.txt - -# generate edgelist from query logs -python3 -m etl-graph query-logs query_log_edges -python3 -m etl-graph query-logs query_log_nodes - -# generate final index -python3 -m etl-graph index -``` - -Alternatively: - -```bash -./scripts/scrape.sh -``` - -Start the web client for visualization. - -```bash -npm run dev -``` - -Deploy to hosting. - -```bash -./scripts/deploy-data.sh -./scripts/deploy-site.sh -``` - -## Development - -A docker image is included for job scheduling. It is recommended to use your -host for developing the web application to avoid networking issues. - -```bash -cp .env.template .env -# configure the environment file as necessary -docker-compose build - -# automatically runs scrape and deploy -docker-compose run --rm app - -# shell into a running container -docker-compose run --rm app bash -``` - -## Archive - -This job was merged from the [archived mozilla/etl-graph -repository](https://github.com/mozilla/etl-graph). diff --git a/jobs/etl-graph/ci_job.yaml b/jobs/etl-graph/ci_job.yaml deleted file mode 100644 index 018ba860..00000000 --- a/jobs/etl-graph/ci_job.yaml +++ /dev/null @@ -1,12 +0,0 @@ -build-job-etl-graph: - docker: - - image: docker:stable-git - steps: - - checkout - - compare-branch: - pattern: ^jobs/etl-graph/ - - setup_remote_docker: - version: 19.03.13 - - run: - name: Build Docker image - command: docker build -t app:build jobs/etl-graph/ diff --git a/jobs/etl-graph/ci_workflow.yaml b/jobs/etl-graph/ci_workflow.yaml deleted file mode 100644 index fdb82196..00000000 --- a/jobs/etl-graph/ci_workflow.yaml +++ /dev/null @@ -1,13 +0,0 @@ -job-etl-graph: - jobs: - - build-job-etl-graph - - gcp-gcr/build-and-push-image: - context: data-eng-airflow-gcr - docker-context: jobs/etl-graph/ - path: jobs/etl-graph/ - image: etl-graph_docker_etl - requires: - - build-job-etl-graph - filters: - branches: - only: main diff --git a/jobs/etl-graph/docker-compose.yml b/jobs/etl-graph/docker-compose.yml deleted file mode 100644 index 12bf9f99..00000000 --- a/jobs/etl-graph/docker-compose.yml +++ /dev/null @@ -1,19 +0,0 @@ -version: "3.4" - -services: - app: - build: - context: . - volumes: - - ./:/app - # Mount the local gcloud sdk configuration when developing. Note that this - # will modify the contents on the host. - - ${CLOUDSDK_CONFIG}/:/tmp/.config/gcloud - # Avoid aliasing node_modules from the host directory - - /app/node_modules - environment: - - CLOUDSDK_CONFIG=/tmp/.config/gcloud - - CLOUDSDK_CORE_PROJECT - command: - bash -c "scripts/scrape.sh && scripts/deploy-data.sh && - scripts/deploy-site.sh" diff --git a/jobs/etl-graph/etl-graph/__init__.py b/jobs/etl-graph/etl-graph/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/jobs/etl-graph/etl-graph/__main__.py b/jobs/etl-graph/etl-graph/__main__.py deleted file mode 100644 index 1f8939a6..00000000 --- a/jobs/etl-graph/etl-graph/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -import logging - -from .commands import cli - -logging.basicConfig(level=logging.DEBUG) -cli() diff --git a/jobs/etl-graph/etl-graph/commands.py b/jobs/etl-graph/etl-graph/commands.py deleted file mode 100644 index 7c50cdc1..00000000 --- a/jobs/etl-graph/etl-graph/commands.py +++ /dev/null @@ -1,137 +0,0 @@ -import json -import logging -import statistics -from pathlib import Path - -import click -import networkx as nx - -from .config import * -from .crawler import fetch_dataset_listing, fetch_table_listing, resolve_view_references -from .utils import ensure_folder, ndjson_load, qualify, run, run_query - -ROOT = Path(__file__).parent.parent - - -@click.group() -def cli(): - pass - - -@cli.command() -@click.option( - "--data-root", type=click.Path(file_okay=False), default=ROOT / "public" / "data" -) -def crawl(data_root): - """Crawl bigquery projects.""" - run(f"gsutil ls gs://{BUCKET}") - run(f"bq ls {PROJECT}:{DATASET}") - - data_root = ensure_folder(data_root) - project = "moz-fx-data-shared-prod" - dataset_listing = fetch_dataset_listing(project, data_root) - tables_listing = fetch_table_listing(dataset_listing, data_root / project) - - views_listing = [row for row in tables_listing if row["table_type"] == "VIEW"] - resolve_view_references(views_listing, data_root / project) - - -@cli.command() -@click.argument("query") -@click.option( - "--data-root", type=click.Path(file_okay=False), default=ROOT / "public" / "data" -) -@click.option("--project", default="moz-fx-data-shared-prod") -def query_logs(query, data_root, project): - """Get all queries made by service accounts in a project.""" - resources = Path(__file__).parent / "resources" - sql = resources / f"{query}.sql" - if not sql.exists(): - items = [p.name.strip(".sql") for p in resources.glob("sql")] - raise ValueError(f"must be one of {items}") - run_query( - sql.read_text(), - dest_table=query, - output=ensure_folder(data_root / project), - project=project, - ) - - -@cli.command() -@click.option( - "--data-root", type=click.Path(file_okay=False), default=ROOT / "public" / "data" -) -def index(data_root): - """Combine all of the files together.""" - # currently, only combine view references and query_edgelist - data_root = ensure_folder(data_root) - edges = [] - nodes = [] - - for edgelist in data_root.glob("**/query_log_edges.json"): - rows = json.loads(edgelist.read_text()) - logging.info( - f"merging {edgelist.relative_to(data_root)} with {len(rows)} query references" - ) - edges += rows - - for nodelist in data_root.glob("**/query_log_nodes.json"): - rows = json.loads(nodelist.read_text()) - logging.info( - f"merging {nodelist.relative_to(data_root)} with {len(rows)} queries" - ) - nodes += rows - - # write the file to disk as both csv and json, csv target is gephi compatible - with (data_root / "edges.json").open("w") as fp: - json.dump(edges, fp, indent=2) - with (data_root / "nodes.json").open("w") as fp: - json.dump(nodes, fp, indent=2) - logging.info("wrote nodes.json") - with (data_root / "edges.csv").open("w") as fp: - fp.write("Source,Target\n") - for edge in edges: - fp.write(f"{edge['referenced_table']},{edge['destination_table']}\n") - logging.info("wrote edges.csv") - - # generate some stats - stats = {} - G = nx.DiGraph() - for edge in edges: - G.add_edge(edge["referenced_table"], edge["destination_table"]) - stats["number_of_nodes"] = G.number_of_nodes() - stats["number_of_edges"] = G.number_of_edges() - stats["in_degree"] = sorted(dict(G.in_degree()).values()) - stats["out_degree"] = sorted(dict(G.out_degree()).values()) - stats["degree"] = sorted(dict(G.degree()).values()) - for value in ["in_degree", "out_degree", "degree"]: - stats[f"avg_{value}"] = statistics.mean(stats[value]) - stats[ - "number_strongly_connected_components" - ] = nx.number_strongly_connected_components(G) - stats["number_weakly_connected_components"] = nx.number_weakly_connected_components( - G - ) - - with (data_root / "network_stats.json").open("w") as fp: - json.dump(stats, fp, indent=2) - logging.info("wrote network_stats.json") - - # also generate a manifest so we can download the files via the app - with (data_root / "manifest.json").open("w") as fp: - json.dump( - sorted( - [ - { - "path": str(p.relative_to(data_root.parent)), - "size_bytes": p.stat().st_size, - } - for p in data_root.glob("**/*") - if p.name != "manifest.json" and p.is_file() - ], - key=lambda x: x["path"], - ), - fp, - indent=2, - ) - logging.info("wrote manifest.json") diff --git a/jobs/etl-graph/etl-graph/config.py b/jobs/etl-graph/etl-graph/config.py deleted file mode 100644 index 04cddef4..00000000 --- a/jobs/etl-graph/etl-graph/config.py +++ /dev/null @@ -1,4 +0,0 @@ -PROJECT = "etl-graph" -DATASET = "intermediate" -BUCKET = PROJECT -MAX_CONCURRENCY = 8 diff --git a/jobs/etl-graph/etl-graph/crawler.py b/jobs/etl-graph/etl-graph/crawler.py deleted file mode 100644 index f6a1e779..00000000 --- a/jobs/etl-graph/etl-graph/crawler.py +++ /dev/null @@ -1,117 +0,0 @@ -import json -import multiprocessing -import tempfile -from functools import partial -from pathlib import Path - -import tqdm - -from .config import * -from .utils import ensure_folder, run, run_query - - -class TableType: - # this contains only the views and the view defintions, but otherwise - # consistent with tables - VIEW = "VIEWS" - TABLE = "TABLES" - - -def fetch_dataset_listing(project: str, data_root: Path): - return run_query( - f"select * from `{project}`.INFORMATION_SCHEMA.SCHEMATA", - "dataset_listing", - ensure_folder(data_root / project), - ) - - -def _generate_table_listing_sql(listing: list, table_type: TableType) -> str: - datasets = [ - f'`{entry["catalog_name"]}`.{entry["schema_name"]}' - for entry in listing - # TODO: this is brittle, replace with a real test of auth - if entry["schema_name"] != "payload_bytes_raw" - ] - queries = [ - f"SELECT * FROM {dataset}.INFORMATION_SCHEMA.{table_type}" - for dataset in datasets - ] - return "\nUNION ALL\n".join(queries) - - -def fetch_table_listing( - dataset_listing: list, project_root: Path, table_type: TableType = TableType.TABLE -): - sql = _generate_table_listing_sql(dataset_listing, table_type) - name = f"{table_type.lower()}_listing" - with (project_root / f"{name}.sql").open("w") as fp: - fp.write(sql) - return run_query(sql, name, project_root) - - -def _view_dryrun(view_root, view): - project_id = view["table_catalog"] - dataset_id = view["table_schema"] - table_id = view["table_name"] - - qualified_name = f"{dataset_id}.{table_id}" - base_query = f"SELECT * from `{project_id}`.{qualified_name}" - where_clauses = [ - "where date(submission_timestamp) = date_sub(current_date, interval 1 day)", - "where submission_date = date_sub(current_date, interval 1 day)", - ] - queries = [f"{base_query} {clause}" for clause in where_clauses] + [base_query] - data = None - for query in queries: - try: - # see NOTES.md for examples of the full response - result = run( - [ - "bq", - "query", - "--format=json", - "--use_legacy_sql=false", - "--dry_run", - query, - ] - ) - data = json.loads(result) - break - except: - # Error in query string: ... - continue - if not data: - print(f"unable to resolve {project_id}:{qualified_name}") - return - with (view_root / f"{qualified_name}.json").open("w") as fp: - subset = data["statistics"] - # not needed at the moment - del subset["query"]["schema"] - # add some extra metadata for our sanity, in the convention already laid - # out by the query dryrun - subset = { - **dict(projectId=project_id, tableId=table_id, datasetId=dataset_id), - **subset, - } - json.dump(subset, fp, indent=2) - - -def resolve_view_references(view_listing, project_root): - # we don't really care about intermediate files - view_root = Path(tempfile.mkdtemp()) - - pool = multiprocessing.Pool(MAX_CONCURRENCY) - for _ in tqdm.tqdm( - pool.imap_unordered(partial(_view_dryrun, view_root), view_listing), - total=len(view_listing), - ): - pass - - results = [] - for view in view_root.glob("*.json"): - data = json.load(view.open()) - results.append(data) - - # merge into a single json file, which fits into memory - with (project_root / "views_references.json").open("w") as fp: - json.dump(results, fp, indent=2) diff --git a/jobs/etl-graph/etl-graph/resources/query_log_edges.sql b/jobs/etl-graph/etl-graph/resources/query_log_edges.sql deleted file mode 100644 index c049d03f..00000000 --- a/jobs/etl-graph/etl-graph/resources/query_log_edges.sql +++ /dev/null @@ -1,93 +0,0 @@ -CREATE TEMP FUNCTION qualified_name( - meta STRUCT -) -RETURNS string AS ( - CONCAT(meta.project_id, ":", meta.dataset_id, ".", meta.table_id) -); - -CREATE TEMP FUNCTION strip_suffix(name string) -RETURNS string AS ( - -- Get rid of the date partition if it exists in the table name, and then extract everything up to the version part. - -- If the regex fails, just return the name without the partition. - coalesce( - REGEXP_EXTRACT(SPLIT(name, "$")[OFFSET(0)], r"^(.*:.*\..*_v[0-9]+)"), - SPLIT(name, "$")[OFFSET(0)] - ) -); - - -- NOTE: this will capture all links between tables in history. If the queries change over time, then this - -- may misrepresent the dependencies. One way to solve this is to take the most recent job_id for a destination table - -- and *then* explode. -WITH extracted AS ( - SELECT - user_email, - job_id, - creation_time, - destination_table, - referenced_tables, - query - FROM - `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT - WHERE - creation_time > TIMESTAMP_SUB(current_timestamp, INTERVAL 90 day) - AND user_email LIKE "%gserviceaccount.com" - AND error_result IS NULL - AND state = "DONE" - -- dont care about destination tables without references at the moment - AND referenced_tables IS NOT NULL - AND NOT STARTS_WITH(destination_table.dataset_id, "_") -), -transformed AS ( - SELECT - * EXCEPT (destination_table, referenced_tables, project_id, dataset_id, table_id), - strip_suffix(qualified_name(destination_table)) AS destination_table, - strip_suffix(qualified_name(referenced_table)) AS referenced_table, - FROM - extracted, - extracted.referenced_tables AS referenced_table - WHERE - NOT STARTS_WITH(referenced_table.dataset_id, "_") -), -creation_time_diff AS ( - SELECT - DISTINCT destination_table, - creation_time, - LAG(creation_time) OVER ( - PARTITION BY - destination_table - ORDER BY - creation_time - ) AS prev_creation_time - FROM - transformed -), -creation_time_freq AS ( - SELECT - destination_table, - ROUND(AVG(TIMESTAMP_DIFF(creation_time, prev_creation_time, minute)) / 60, 1) AS freq_avg, - ROUND(stddev(TIMESTAMP_DIFF(creation_time, prev_creation_time, minute)) / 60, 1) AS freq_std - FROM - creation_time_diff - GROUP BY - 1 -), -edges AS ( - SELECT - destination_table, - referenced_table, - MAX(creation_time) AS creation_timestamp, - CAST(COUNT(DISTINCT job_id) AS FLOAT64) AS n_jobs, - FROM - transformed - GROUP BY - 1, - 2 -) -SELECT - * -FROM - edges -JOIN - creation_time_freq -USING - (destination_table) diff --git a/jobs/etl-graph/etl-graph/resources/query_log_nodes.sql b/jobs/etl-graph/etl-graph/resources/query_log_nodes.sql deleted file mode 100644 index 6b3597a3..00000000 --- a/jobs/etl-graph/etl-graph/resources/query_log_nodes.sql +++ /dev/null @@ -1,63 +0,0 @@ -CREATE TEMP FUNCTION qualified_name( - meta STRUCT -) -RETURNS string AS ( - CONCAT(meta.project_id, ":", meta.dataset_id, ".", meta.table_id) -); - -CREATE TEMP FUNCTION strip_suffix(name string) -RETURNS string AS ( - -- Get rid of the date partition if it exists in the table name, and then extract everything up to the version part. - -- If the regex fails, just return the name without the partition. - coalesce( - REGEXP_EXTRACT(SPLIT(name, "$")[OFFSET(0)], r"^(.*:.*\..*_v[0-9]+)"), - SPLIT(name, "$")[OFFSET(0)] - ) -); - - -- NOTE: this will capture all links between tables in history. If the queries change over time, then this - -- may misrepresent the dependencies. One way to solve this is to take the most recent job_id for a destination table - -- and *then* explode. -WITH extracted AS ( - SELECT - user_email, - job_id, - creation_time, - destination_table, - referenced_tables, - query - FROM - `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT - WHERE - creation_time > TIMESTAMP_SUB(current_timestamp, INTERVAL 90 day) - AND user_email LIKE "%gserviceaccount.com" - AND error_result IS NULL - AND state = "DONE" - -- dont care about destination tables without references at the moment - AND referenced_tables IS NOT NULL - AND NOT STARTS_WITH(destination_table.dataset_id, "_") -), -transformed AS ( - SELECT - DISTINCT * EXCEPT (destination_table, referenced_tables, project_id, dataset_id, table_id), - strip_suffix(qualified_name(destination_table)) AS destination_table, - FROM - extracted, - extracted.referenced_tables AS referenced_table - WHERE - NOT STARTS_WITH(referenced_table.dataset_id, "_") -) -SELECT - destination_table, - array_agg(query ORDER BY creation_time DESC LIMIT 1)[offset(0)] AS query, - array_agg( - STRUCT(job_id, user_email, creation_time) - ORDER BY - creation_time DESC - LIMIT - 10 - ) AS most_recent_jobs -FROM - transformed -GROUP BY - 1 diff --git a/jobs/etl-graph/etl-graph/resources/query_logs.sql b/jobs/etl-graph/etl-graph/resources/query_logs.sql deleted file mode 100644 index 80b9e7b9..00000000 --- a/jobs/etl-graph/etl-graph/resources/query_logs.sql +++ /dev/null @@ -1,67 +0,0 @@ -CREATE TEMP FUNCTION qualified_name( - meta STRUCT -) -RETURNS string AS ( - CONCAT(meta.project_id, ":", meta.dataset_id, ".", meta.table_id) -); - -CREATE TEMP FUNCTION strip_suffix(name string) -RETURNS string AS ( - -- Get rid of the date partition if it exists in the table name, and then extract everything up to the version part. - -- If the regex fails, just return the name without the partition. - coalesce( - REGEXP_EXTRACT(SPLIT(name, "$")[OFFSET(0)], r"^(.*:.*\..*_v[0-9]+)"), - SPLIT(name, "$")[OFFSET(0)] - ) -); - - -- NOTE: this will capture all links between tables in history. If the queries change over time, then this - -- may misrepresent the dependencies. One way to solve this is to take the most recent job_id for a destination table - -- and *then* explode. -WITH extracted AS ( - SELECT - user_email, - job_id, - creation_time, - destination_table, - referenced_tables, - query - FROM - `region-us`.INFORMATION_SCHEMA.JOBS_BY_PROJECT - WHERE - error_result IS NULL - AND state = "DONE" - -- dont care about destination tables without references at the moment - AND referenced_tables IS NOT NULL - AND NOT STARTS_WITH(destination_table.dataset_id, "_") -), -transformed AS ( - SELECT - * EXCEPT (destination_table, referenced_tables, project_id, dataset_id, table_id), - strip_suffix(qualified_name(destination_table)) AS destination_table, - strip_suffix(qualified_name(referenced_table)) AS referenced_table, - FROM - extracted, - extracted.referenced_tables AS referenced_table - WHERE - NOT STARTS_WITH(referenced_table.dataset_id, "_") -) -SELECT - user_email, - job_id, - creation_time, - destination_table, - ARRAY_AGG(referenced_table ORDER BY referenced_table) AS referenced_tables, - MIN(query) AS query -FROM - transformed -WHERE - creation_time > TIMESTAMP_SUB(current_timestamp, INTERVAL 90 day) - AND user_email LIKE "%gserviceaccount.com" -GROUP BY - 1, - 2, - 3, - 4 -ORDER BY - creation_time DESC diff --git a/jobs/etl-graph/etl-graph/utils.py b/jobs/etl-graph/etl-graph/utils.py deleted file mode 100644 index 10f5618c..00000000 --- a/jobs/etl-graph/etl-graph/utils.py +++ /dev/null @@ -1,93 +0,0 @@ -import json -import logging -import subprocess -import tempfile -from pathlib import Path -from typing import List, Union - -from .config import * - - -def ensure_folder(path: Path) -> Path: - path.mkdir(parents=True, exist_ok=True) - return path - - -def ndjson_load(path: Path) -> List[dict]: - data = [] - with path.open() as fp: - for line in fp.readlines(): - data.append(json.loads(line)) - return data - - -def run(command: Union[str, List[str]], **kwargs) -> str: - """Simple wrapper around subprocess.run that returns stdout and raises exceptions on errors.""" - logging.debug(f"running command: {command}") - if isinstance(command, list): - args = command - elif isinstance(command, str): - args = command.split() - else: - raise RuntimeError(f"run command is invalid: {command}") - - try: - result = ( - subprocess.run( - args, stdout=subprocess.PIPE, **{**dict(check=True), **kwargs} - ) - .stdout.decode() - .strip() - ) - except subprocess.CalledProcessError as exc: - raise RuntimeError( - f"command {exc.cmd} failed with status {exc.returncode}: {exc.output.decode()}" - ) - return result - - -# NOTE: I could use the google-cloud-bigquery package, but most of my -# development happens in bash. -def run_query(sql: str, dest_table: str, output: Path = None, project=PROJECT) -> dict: - """Run a query, and write a json file containing the query results to the output path""" - # project is the project where the query takes place - intermediate = Path(tempfile.mkdtemp()) - qualified_name = f"{PROJECT}:{DATASET}.{dest_table}" - filename = f"{dest_table}.ndjson" - blob = f"gs://{BUCKET}/{DATASET}/{filename}" - - run( - [ - "bq", - "query", - f"--project_id={project}", - "--format=json", - "--use_legacy_sql=false", - # ignore the results since we'll extract them from an intermediate table - "--max_rows=0", - f"--destination_table={qualified_name}", - "--replace", - sql, - ] - ) - run( - [ - "bq", - "extract", - "--destination_format=NEWLINE_DELIMITED_JSON", - qualified_name, - blob, - ] - ) - run(f"gsutil cp {blob} {intermediate}") - loaded = ndjson_load(intermediate / filename) - # write json instead of ndjson into the output location - result = output / filename.replace(".ndjson", ".json") - with (result).open("w") as fp: - logging.info(f"writing {result}") - json.dump(loaded, fp, indent=2) - return loaded - - -def qualify(project, dataset, table): - return f"{project}:{dataset}.{table}" diff --git a/jobs/etl-graph/package-lock.json b/jobs/etl-graph/package-lock.json deleted file mode 100644 index 0f675b31..00000000 --- a/jobs/etl-graph/package-lock.json +++ /dev/null @@ -1,2329 +0,0 @@ -{ - "name": "etl-graph", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "version": "1.0.0", - "dependencies": { - "bootstrap": "^4.6.0", - "codemirror": "^5.59.2", - "fuse.js": "^6.4.6", - "lodash": "^4.17.20", - "page": "^1.11.6", - "sirv-cli": "^1.0.11", - "sveltestrap": "^3.13.0", - "tabulator-tables": "^4.9.3", - "vis-data": "^7.1.2", - "vis-network": "^9.0.2" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^17.1.0", - "@rollup/plugin-node-resolve": "^11.1.1", - "mdsvex": "^0.8.9", - "rollup": "^2.38.5", - "rollup-plugin-css-only": "^3.1.0", - "rollup-plugin-livereload": "^2.0.0", - "rollup-plugin-svelte": "^7.1.0", - "rollup-plugin-terser": "^7.0.2", - "svelte": "^3.32.2" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "node_modules/@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@egjs/hammerjs": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", - "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", - "peer": true, - "dependencies": { - "@types/hammerjs": "^2.0.36" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.11", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.11.tgz", - "integrity": "sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA==" - }, - "node_modules/@popperjs/core": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.6.0.tgz", - "integrity": "sha512-cPqjjzuFWNK3BSKLm0abspP0sp/IGOli4p5I5fKFAzdS8fvjdOwDCfZqAaIiXd9lPkOWi3SUUfZof3hEb7J/uw==" - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz", - "integrity": "sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^2.30.0" - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.1.1.tgz", - "integrity": "sha512-zlBXR4eRS+2m79TsUZWhsd0slrHUYdRx4JF+aVQm+MI0wsKdlpC2vlDVjmlGvtZY1vsefOT9w3JxvmWSBei+Lg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "node_modules/@types/hammerjs": { - "version": "2.0.38", - "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.38.tgz", - "integrity": "sha512-wuwDzWW1JWh3BZoRftBlKcctjNzR75QFY4/b4zAz7sH1EesA8HBJzke+bF5dxCATNdHHs3X1P5UWanbbUT6chw==", - "peer": true - }, - "node_modules/@types/node": { - "version": "14.14.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.16.tgz", - "integrity": "sha512-naXYePhweTi+BMv11TgioE2/FXU4fSl29HAH1ffxVciNsH3rYXjNP2yM8wqmSm7jS20gM8TIklKiTen+1iVncw==", - "dev": true - }, - "node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true - }, - "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/anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bootstrap": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", - "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - }, - "peerDependencies": { - "jquery": "1.9.1 - 3", - "popper.js": "^1.16.1" - } - }, - "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==", - "dev": true, - "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/buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "node_modules/builtin-modules": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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/chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.2" - } - }, - "node_modules/clipboard": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", - "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", - "dev": true, - "optional": true, - "dependencies": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, - "node_modules/codemirror": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.59.2.tgz", - "integrity": "sha512-/D5PcsKyzthtSy2NNKCyJi3b+htRkoKv3idswR/tR6UAvMNKA7SrmyZy6fOONJxSRs1JlUWEDAbxqfdArbK8iA==" - }, - "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/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "peer": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/console-clear": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/console-clear/-/console-clear-1.1.1.tgz", - "integrity": "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", - "dev": true, - "optional": true - }, - "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": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "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/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": 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==", - "dev": true - }, - "node_modules/fuse.js": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.4.6.tgz", - "integrity": "sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", - "engines": { - "node": ">=4" - } - }, - "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": "*" - } - }, - "node_modules/glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", - "dev": true, - "optional": true, - "dependencies": { - "delegate": "^3.1.2" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "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==", - "dev": true - }, - "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-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "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-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/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==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jquery": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", - "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==", - "peer": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/keycharm": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.4.0.tgz", - "integrity": "sha512-TyQTtsabOVv3MeOpR92sIKk/br9wxS+zGj4BG7CR8YbK4jM3tyIBaF0zhzeBUMx36/Q/iQLOKKOT+3jOQtemRQ==", - "peer": true - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "engines": { - "node": ">=6" - } - }, - "node_modules/livereload": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.1.tgz", - "integrity": "sha512-9g7sua11kkyZNo2hLRCG3LuZZwqexoyEyecSlV8cAsfAVVCZqLzVir6XDqmH0r+Vzgnd5LrdHDMyjtFnJQLAYw==", - "dev": true, - "dependencies": { - "chokidar": "^3.3.0", - "livereload-js": "^3.1.0", - "opts": ">= 1.2.0", - "ws": "^6.2.1" - }, - "bin": { - "livereload": "bin/livereload.js" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/livereload-js": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.3.1.tgz", - "integrity": "sha512-CBu1gTEfzVhlOK1WASKAAJ9Qx1fHECTq0SUB67sfxwQssopTyvzqTlgl+c0h9pZ6V+Fzd2rc510ppuNusg9teQ==", - "dev": true - }, - "node_modules/local-access": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/local-access/-/local-access-1.1.0.tgz", - "integrity": "sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "node_modules/lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" - }, - "node_modules/lodash.tonumber": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/lodash.tonumber/-/lodash.tonumber-4.0.3.tgz", - "integrity": "sha1-C5azGzVnJ5Prf1pj7nkfG56QJdk=" - }, - "node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, - "node_modules/mdsvex": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/mdsvex/-/mdsvex-0.8.9.tgz", - "integrity": "sha512-9CDBDV29IVNJsJWDlCg1UwascU8QmuHsYEXJH2ZGsf7lCCWUDSwbOmR+I77tm8D2YQrPsbLCLq/UndUMJck3Cw==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.3", - "prismjs": "^1.17.1", - "vfile-message": "^2.0.4" - }, - "peerDependencies": { - "svelte": "3.x" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/mime": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", - "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mri": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", - "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", - "engines": { - "node": ">=4" - } - }, - "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/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/opts": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz", - "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", - "dev": true - }, - "node_modules/page": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/page/-/page-1.11.6.tgz", - "integrity": "sha512-P6e2JfzkBrPeFCIPplLP7vDDiU84RUUZMrWdsH4ZBGJ8OosnwFkcUkBHp1DTIjuipLliw9yQn/ZJsXZvarsO+g==", - "dependencies": { - "path-to-regexp": "~1.2.1" - } - }, - "node_modules/page/node_modules/path-to-regexp": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.2.1.tgz", - "integrity": "sha1-szcFwUAjTYc8hyHHuf2LVB7Tr/k=", - "dependencies": { - "isarray": "0.0.1" - } - }, - "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": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", - "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/prismjs": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", - "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", - "dev": true, - "dependencies": { - "clipboard": "^2.0.0" - }, - "optionalDependencies": { - "clipboard": "^2.0.0" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-relative": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "dependencies": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - }, - "node_modules/rollup": { - "version": "2.38.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz", - "integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==", - "dev": true, - "dependencies": { - "fsevents": "~2.3.1" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.1" - } - }, - "node_modules/rollup-plugin-css-only": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz", - "integrity": "sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "4" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/rollup-plugin-css-only/node_modules/@rollup/pluginutils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz", - "integrity": "sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/rollup-plugin-livereload": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.0.tgz", - "integrity": "sha512-oC/8NqumGYuphkqrfszOHUUIwzKsaHBICw6QRwT5uD07gvePTS+HW+GFwu6f9K8W02CUuTvtIM9AWJrbj4wE1A==", - "dev": true, - "dependencies": { - "livereload": "^0.9.1" - }, - "engines": { - "node": ">=8.3" - } - }, - "node_modules/rollup-plugin-svelte": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", - "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", - "dev": true, - "dependencies": { - "require-relative": "^0.8.7", - "rollup-pluginutils": "^2.8.2" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "rollup": ">=2.0.0", - "svelte": ">=3.5.0" - } - }, - "node_modules/rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - } - }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } - }, - "node_modules/rollup-pluginutils/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, - "node_modules/rollup/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/sade": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", - "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==", - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">= 6" - } - }, - "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==", - "dev": true - }, - "node_modules/select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", - "dev": true, - "optional": true - }, - "node_modules/semiver": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", - "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/sirv": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.11.tgz", - "integrity": "sha512-SR36i3/LSWja7AJNRBz4fF/Xjpn7lQFI30tZ434dIy+bitLYSP+ZEenHg36i23V2SGEz+kqjksg0uOGZ5LPiqg==", - "dependencies": { - "@polka/url": "^1.0.0-next.9", - "mime": "^2.3.1", - "totalist": "^1.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/sirv-cli": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-1.0.11.tgz", - "integrity": "sha512-L8NILoRSBd38VcfFcERYCaVCnWPBLo9G6u/a37UJ8Ysv4DfjizMbFBcM+SswNnndJienhR6qy8KFuAEaeL4g8Q==", - "dependencies": { - "console-clear": "^1.1.0", - "get-port": "^3.2.0", - "kleur": "^3.0.0", - "local-access": "^1.0.1", - "sade": "^1.6.0", - "semiver": "^1.0.0", - "sirv": "^1.0.11", - "tinydate": "^1.0.0" - }, - "bin": { - "sirv": "bin.js" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "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/svelte": { - "version": "3.32.2", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.32.2.tgz", - "integrity": "sha512-Zxh1MQQl/+vnToKbU1Per+PoMN8Jb2MeKJcGxiOsCGR677hXw7jkMfbnNXq33+dxIzV/HfA4xtoSPJrqeB0VUg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/sveltestrap": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/sveltestrap/-/sveltestrap-3.13.0.tgz", - "integrity": "sha512-SRktDio6C/PoLK6Yc/2kSCT18CPI/6bedM17vyaRzoRJf5hdWCm6LOGM5q9aP4TK6soOTYDYkS5PMhCXxGah+Q==", - "dependencies": { - "@popperjs/core": "^2.6.0", - "lodash.isobject": "^3.0.2", - "lodash.tonumber": "^4.0.3" - }, - "peerDependencies": { - "svelte": "^3.4.4" - } - }, - "node_modules/tabulator-tables": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-4.9.3.tgz", - "integrity": "sha512-iwwQqAEGGxlgrBpcmJJvMJrfjGLcCXOB3AOb/DGkXqBy1YKoYA36hIl7qXGp6Jo8dSkzFAlDT6pKLZgyhs9OnQ==" - }, - "node_modules/terser": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", - "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", - "dev": true, - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "peer": true - }, - "node_modules/tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "dev": true, - "optional": true - }, - "node_modules/tinydate": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", - "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==", - "engines": { - "node": ">=4" - } - }, - "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/totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", - "engines": { - "node": ">=6" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "peer": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/vfile-message": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", - "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", - "dev": true, - "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vis-data": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/vis-data/-/vis-data-7.1.2.tgz", - "integrity": "sha512-RPSegFxEcnp3HUEJSzhS2vBdbJ2PSsrYYuhRlpHp2frO/MfRtTYbIkkLZmPkA/Sg3pPfBlR235gcoKbtdm4mbw==", - "hasInstallScript": true - }, - "node_modules/vis-network": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/vis-network/-/vis-network-9.0.2.tgz", - "integrity": "sha512-0UFs81YsGcHSzZG5d3AsDQDvREF0h0/mAqzRDV+62jq0Tj5fpJzB+xvcbRuZfQIfrYN7DqNsHXvNOthAuCAlrg==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/visjs" - }, - "peerDependencies": { - "@egjs/hammerjs": "^2.0.0", - "component-emitter": "^1.3.0", - "keycharm": "^0.2.0 || ^0.3.0 || ^0.4.0", - "timsort": "^0.3.0", - "uuid": "^3.4.0 || ^7.0.0 || ^8.0.0", - "vis-data": "^7.0.0", - "vis-util": "^5.0.1" - } - }, - "node_modules/vis-util": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/vis-util/-/vis-util-5.0.2.tgz", - "integrity": "sha512-oPDmPc4o0uQLoKpKai2XD1DjrhYsA7MRz75Wx9KmfX84e9LLgsbno7jVL5tR0K9eNVQkD6jf0Ei8NtbBHDkF1A==", - "peer": true, - "engines": { - "node": ">=8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/visjs" - }, - "peerDependencies": { - "@egjs/hammerjs": "^2.0.0", - "component-emitter": "^1.3.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "dependencies": { - "async-limiter": "~1.0.0" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@egjs/hammerjs": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", - "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", - "peer": true, - "requires": { - "@types/hammerjs": "^2.0.36" - } - }, - "@polka/url": { - "version": "1.0.0-next.11", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.11.tgz", - "integrity": "sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA==" - }, - "@popperjs/core": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.6.0.tgz", - "integrity": "sha512-cPqjjzuFWNK3BSKLm0abspP0sp/IGOli4p5I5fKFAzdS8fvjdOwDCfZqAaIiXd9lPkOWi3SUUfZof3hEb7J/uw==" - }, - "@rollup/plugin-commonjs": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz", - "integrity": "sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - } - }, - "@rollup/plugin-node-resolve": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.1.1.tgz", - "integrity": "sha512-zlBXR4eRS+2m79TsUZWhsd0slrHUYdRx4JF+aVQm+MI0wsKdlpC2vlDVjmlGvtZY1vsefOT9w3JxvmWSBei+Lg==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - } - }, - "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "dependencies": { - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - } - } - }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "@types/hammerjs": { - "version": "2.0.38", - "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.38.tgz", - "integrity": "sha512-wuwDzWW1JWh3BZoRftBlKcctjNzR75QFY4/b4zAz7sH1EesA8HBJzke+bF5dxCATNdHHs3X1P5UWanbbUT6chw==", - "peer": true - }, - "@types/node": { - "version": "14.14.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.16.tgz", - "integrity": "sha512-naXYePhweTi+BMv11TgioE2/FXU4fSl29HAH1ffxVciNsH3rYXjNP2yM8wqmSm7jS20gM8TIklKiTen+1iVncw==", - "dev": true - }, - "@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/unist": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", - "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", - "dev": true - }, - "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, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true - }, - "bootstrap": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", - "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==", - "requires": {} - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "builtin-modules": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", - "dev": true - }, - "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, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", - "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - } - }, - "clipboard": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", - "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", - "dev": true, - "optional": true, - "requires": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, - "codemirror": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.59.2.tgz", - "integrity": "sha512-/D5PcsKyzthtSy2NNKCyJi3b+htRkoKv3idswR/tR6UAvMNKA7SrmyZy6fOONJxSRs1JlUWEDAbxqfdArbK8iA==" - }, - "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, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "peer": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "console-clear": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/console-clear/-/console-clear-1.1.1.tgz", - "integrity": "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==" - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", - "dev": true, - "optional": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "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, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "fuse.js": { - "version": "6.4.6", - "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.4.6.tgz", - "integrity": "sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw==" - }, - "get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=" - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "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" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", - "dev": true, - "optional": true, - "requires": { - "delegate": "^3.1.2" - } - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "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, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "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 - }, - "is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "requires": { - "@types/estree": "*" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "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==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jquery": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", - "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==", - "peer": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "keycharm": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.4.0.tgz", - "integrity": "sha512-TyQTtsabOVv3MeOpR92sIKk/br9wxS+zGj4BG7CR8YbK4jM3tyIBaF0zhzeBUMx36/Q/iQLOKKOT+3jOQtemRQ==", - "peer": true - }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" - }, - "livereload": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.1.tgz", - "integrity": "sha512-9g7sua11kkyZNo2hLRCG3LuZZwqexoyEyecSlV8cAsfAVVCZqLzVir6XDqmH0r+Vzgnd5LrdHDMyjtFnJQLAYw==", - "dev": true, - "requires": { - "chokidar": "^3.3.0", - "livereload-js": "^3.1.0", - "opts": ">= 1.2.0", - "ws": "^6.2.1" - } - }, - "livereload-js": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.3.1.tgz", - "integrity": "sha512-CBu1gTEfzVhlOK1WASKAAJ9Qx1fHECTq0SUB67sfxwQssopTyvzqTlgl+c0h9pZ6V+Fzd2rc510ppuNusg9teQ==", - "dev": true - }, - "local-access": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/local-access/-/local-access-1.1.0.tgz", - "integrity": "sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==" - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" - }, - "lodash.tonumber": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/lodash.tonumber/-/lodash.tonumber-4.0.3.tgz", - "integrity": "sha1-C5azGzVnJ5Prf1pj7nkfG56QJdk=" - }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "mdsvex": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/mdsvex/-/mdsvex-0.8.9.tgz", - "integrity": "sha512-9CDBDV29IVNJsJWDlCg1UwascU8QmuHsYEXJH2ZGsf7lCCWUDSwbOmR+I77tm8D2YQrPsbLCLq/UndUMJck3Cw==", - "dev": true, - "requires": { - "@types/unist": "^2.0.3", - "prismjs": "^1.17.1", - "vfile-message": "^2.0.4" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "mime": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.0.tgz", - "integrity": "sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mri": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", - "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==" - }, - "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 - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "opts": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz", - "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", - "dev": true - }, - "page": { - "version": "1.11.6", - "resolved": "https://registry.npmjs.org/page/-/page-1.11.6.tgz", - "integrity": "sha512-P6e2JfzkBrPeFCIPplLP7vDDiU84RUUZMrWdsH4ZBGJ8OosnwFkcUkBHp1DTIjuipLliw9yQn/ZJsXZvarsO+g==", - "requires": { - "path-to-regexp": "~1.2.1" - }, - "dependencies": { - "path-to-regexp": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.2.1.tgz", - "integrity": "sha1-szcFwUAjTYc8hyHHuf2LVB7Tr/k=", - "requires": { - "isarray": "0.0.1" - } - } - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", - "peer": true - }, - "prismjs": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.23.0.tgz", - "integrity": "sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==", - "dev": true, - "requires": { - "clipboard": "^2.0.0" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "require-relative": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", - "dev": true - }, - "resolve": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", - "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", - "dev": true, - "requires": { - "is-core-module": "^2.1.0", - "path-parse": "^1.0.6" - } - }, - "rollup": { - "version": "2.38.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz", - "integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==", - "dev": true, - "requires": { - "fsevents": "~2.3.1" - }, - "dependencies": { - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - } - } - }, - "rollup-plugin-css-only": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz", - "integrity": "sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==", - "dev": true, - "requires": { - "@rollup/pluginutils": "4" - }, - "dependencies": { - "@rollup/pluginutils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.0.tgz", - "integrity": "sha512-TrBhfJkFxA+ER+ew2U2/fHbebhLT/l/2pRk0hfj9KusXUuRXd2v0R58AfaZK9VXDQ4TogOSEmICVrQAA3zFnHQ==", - "dev": true, - "requires": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - } - } - } - }, - "rollup-plugin-livereload": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.0.tgz", - "integrity": "sha512-oC/8NqumGYuphkqrfszOHUUIwzKsaHBICw6QRwT5uD07gvePTS+HW+GFwu6f9K8W02CUuTvtIM9AWJrbj4wE1A==", - "dev": true, - "requires": { - "livereload": "^0.9.1" - } - }, - "rollup-plugin-svelte": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", - "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", - "dev": true, - "requires": { - "require-relative": "^0.8.7", - "rollup-pluginutils": "^2.8.2" - } - }, - "rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1" - }, - "dependencies": { - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - } - } - }, - "sade": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", - "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==", - "requires": { - "mri": "^1.1.0" - } - }, - "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==", - "dev": true - }, - "select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", - "dev": true, - "optional": true - }, - "semiver": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", - "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==" - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "sirv": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.11.tgz", - "integrity": "sha512-SR36i3/LSWja7AJNRBz4fF/Xjpn7lQFI30tZ434dIy+bitLYSP+ZEenHg36i23V2SGEz+kqjksg0uOGZ5LPiqg==", - "requires": { - "@polka/url": "^1.0.0-next.9", - "mime": "^2.3.1", - "totalist": "^1.0.0" - } - }, - "sirv-cli": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-1.0.11.tgz", - "integrity": "sha512-L8NILoRSBd38VcfFcERYCaVCnWPBLo9G6u/a37UJ8Ysv4DfjizMbFBcM+SswNnndJienhR6qy8KFuAEaeL4g8Q==", - "requires": { - "console-clear": "^1.1.0", - "get-port": "^3.2.0", - "kleur": "^3.0.0", - "local-access": "^1.0.1", - "sade": "^1.6.0", - "semiver": "^1.0.0", - "sirv": "^1.0.11", - "tinydate": "^1.0.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "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, - "requires": { - "has-flag": "^3.0.0" - } - }, - "svelte": { - "version": "3.32.2", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.32.2.tgz", - "integrity": "sha512-Zxh1MQQl/+vnToKbU1Per+PoMN8Jb2MeKJcGxiOsCGR677hXw7jkMfbnNXq33+dxIzV/HfA4xtoSPJrqeB0VUg==" - }, - "sveltestrap": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/sveltestrap/-/sveltestrap-3.13.0.tgz", - "integrity": "sha512-SRktDio6C/PoLK6Yc/2kSCT18CPI/6bedM17vyaRzoRJf5hdWCm6LOGM5q9aP4TK6soOTYDYkS5PMhCXxGah+Q==", - "requires": { - "@popperjs/core": "^2.6.0", - "lodash.isobject": "^3.0.2", - "lodash.tonumber": "^4.0.3" - } - }, - "tabulator-tables": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-4.9.3.tgz", - "integrity": "sha512-iwwQqAEGGxlgrBpcmJJvMJrfjGLcCXOB3AOb/DGkXqBy1YKoYA36hIl7qXGp6Jo8dSkzFAlDT6pKLZgyhs9OnQ==" - }, - "terser": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.5.1.tgz", - "integrity": "sha512-6VGWZNVP2KTUcltUQJ25TtNjx/XgdDsBDKGt8nN0MpydU36LmbPPcMBd2kmtZNNGVVDLg44k7GKeHHj+4zPIBQ==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.19" - } - }, - "timsort": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", - "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", - "peer": true - }, - "tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "dev": true, - "optional": true - }, - "tinydate": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", - "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==" - }, - "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, - "requires": { - "is-number": "^7.0.0" - } - }, - "totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" - }, - "unist-util-stringify-position": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", - "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", - "dev": true, - "requires": { - "@types/unist": "^2.0.2" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "peer": true - }, - "vfile-message": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", - "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", - "dev": true, - "requires": { - "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^2.0.0" - } - }, - "vis-data": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/vis-data/-/vis-data-7.1.2.tgz", - "integrity": "sha512-RPSegFxEcnp3HUEJSzhS2vBdbJ2PSsrYYuhRlpHp2frO/MfRtTYbIkkLZmPkA/Sg3pPfBlR235gcoKbtdm4mbw==" - }, - "vis-network": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/vis-network/-/vis-network-9.0.2.tgz", - "integrity": "sha512-0UFs81YsGcHSzZG5d3AsDQDvREF0h0/mAqzRDV+62jq0Tj5fpJzB+xvcbRuZfQIfrYN7DqNsHXvNOthAuCAlrg==", - "requires": {} - }, - "vis-util": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/vis-util/-/vis-util-5.0.2.tgz", - "integrity": "sha512-oPDmPc4o0uQLoKpKai2XD1DjrhYsA7MRz75Wx9KmfX84e9LLgsbno7jVL5tR0K9eNVQkD6jf0Ei8NtbBHDkF1A==", - "peer": true, - "requires": {} - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - } - } -} diff --git a/jobs/etl-graph/package.json b/jobs/etl-graph/package.json deleted file mode 100644 index 4a202724..00000000 --- a/jobs/etl-graph/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "etl-graph", - "version": "1.0.0", - "scripts": { - "build": "rollup -c", - "dev": "rollup -c -w", - "start": "sirv public --single" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^17.1.0", - "@rollup/plugin-node-resolve": "^11.1.1", - "mdsvex": "^0.8.9", - "rollup": "^2.38.5", - "rollup-plugin-css-only": "^3.1.0", - "rollup-plugin-livereload": "^2.0.0", - "rollup-plugin-svelte": "^7.1.0", - "rollup-plugin-terser": "^7.0.2", - "svelte": "^3.32.2" - }, - "dependencies": { - "bootstrap": "^4.6.0", - "codemirror": "^5.59.2", - "fuse.js": "^6.4.6", - "lodash": "^4.17.20", - "page": "^1.11.6", - "sirv-cli": "^1.0.11", - "sveltestrap": "^3.13.0", - "tabulator-tables": "^4.9.3", - "vis-data": "^7.1.2", - "vis-network": "^9.0.2" - } -} diff --git a/jobs/etl-graph/public/index.html b/jobs/etl-graph/public/index.html deleted file mode 100644 index 41a36de6..00000000 --- a/jobs/etl-graph/public/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - BigQuery ETL Query Network - - - - - - diff --git a/jobs/etl-graph/requirements.in b/jobs/etl-graph/requirements.in deleted file mode 100644 index 7767bc08..00000000 --- a/jobs/etl-graph/requirements.in +++ /dev/null @@ -1,3 +0,0 @@ -tqdm -click -networkx \ No newline at end of file diff --git a/jobs/etl-graph/requirements.txt b/jobs/etl-graph/requirements.txt deleted file mode 100644 index d70277c5..00000000 --- a/jobs/etl-graph/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -# -# This file is autogenerated by pip-compile -# To update, run: -# -# pip-compile -# -click==8.0.4 -decorator==4.4.2 # via networkx -networkx==2.5 -tqdm==4.46.1 diff --git a/jobs/etl-graph/rollup.config.js b/jobs/etl-graph/rollup.config.js deleted file mode 100644 index ccb9fe10..00000000 --- a/jobs/etl-graph/rollup.config.js +++ /dev/null @@ -1,83 +0,0 @@ -import svelte from "rollup-plugin-svelte"; -import commonjs from "@rollup/plugin-commonjs"; -import resolve from "@rollup/plugin-node-resolve"; -import livereload from "rollup-plugin-livereload"; -import { terser } from "rollup-plugin-terser"; -import css from "rollup-plugin-css-only"; -import { mdsvex } from "mdsvex"; - -const production = !process.env.ROLLUP_WATCH; - -function serve() { - let server; - - function toExit() { - if (server) server.kill(0); - } - - return { - writeBundle() { - if (server) return; - server = require("child_process").spawn( - "npm", - ["run", "start", "--", "--dev"], - { - stdio: ["ignore", "inherit", "inherit"], - shell: true, - } - ); - - process.on("SIGTERM", toExit); - process.on("exit", toExit); - }, - }; -} - -export default { - input: "src/main.js", - output: { - sourcemap: true, - format: "iife", - name: "app", - file: "public/build/bundle.js", - }, - plugins: [ - svelte({ - extensions: [".svelte", ".svx"], - preprocess: mdsvex(), - compilerOptions: { - // enable run-time checks when not in production - dev: !production, - }, - }), - // we'll extract any component CSS out into - // a separate file - better for performance - css({ output: "bundle.css" }), - - // If you have external dependencies installed from - // npm, you'll most likely need these plugins. In - // some cases you'll need additional configuration - - // consult the documentation for details: - // https://github.com/rollup/plugins/tree/master/packages/commonjs - resolve({ - browser: true, - dedupe: ["svelte"], - }), - commonjs(), - - // In dev mode, call `npm run start` once - // the bundle has been generated - !production && serve(), - - // Watch the `public` directory and refresh the - // browser on changes when not in production - !production && livereload("public"), - - // If we're building for production (npm run build - // instead of npm run dev), minify - production && terser(), - ], - watch: { - clearScreen: false, - }, -}; diff --git a/jobs/etl-graph/screenshot.png b/jobs/etl-graph/screenshot.png deleted file mode 100644 index 0e71c9c36e3b11f517d021bcea09ab35eb97ec70..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63970 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�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 diff --git a/jobs/etl-graph/scripts/deploy-data.sh b/jobs/etl-graph/scripts/deploy-data.sh deleted file mode 100755 index 0b7046f0..00000000 --- a/jobs/etl-graph/scripts/deploy-data.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# Synchronizes assets into the bucket read by protosaur.dev - -set -ex - -cd "$(dirname "$0")/.." - -BUCKET=${BUCKET:-"gs://etl-graph"} - -gsutil -m rsync -r -d public/data $BUCKET/site/data diff --git a/jobs/etl-graph/scripts/deploy-site.sh b/jobs/etl-graph/scripts/deploy-site.sh deleted file mode 100755 index 8775e9e8..00000000 --- a/jobs/etl-graph/scripts/deploy-site.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash -# Synchronizes site assets into the bucket read by protosaur.dev - -set -ex - -cd "$(dirname "$0")/.." - -BUCKET=${BUCKET:-"gs://etl-graph"} - -npm run build -gsutil -m rsync -r -d -x data/ public/ $BUCKET/site/ diff --git a/jobs/etl-graph/scripts/scrape.sh b/jobs/etl-graph/scripts/scrape.sh deleted file mode 100755 index bf6a4dad..00000000 --- a/jobs/etl-graph/scripts/scrape.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash -# Run the queries for generating assets - -set -ex - -cd "$(dirname "$0")/.." - -python3 -m etl-graph query-logs query_log_edges --project moz-fx-data-shared-prod -python3 -m etl-graph query-logs query_log_nodes --project moz-fx-data-shared-prod -python3 -m etl-graph index diff --git a/jobs/etl-graph/src/App.svelte b/jobs/etl-graph/src/App.svelte deleted file mode 100644 index f4121556..00000000 --- a/jobs/etl-graph/src/App.svelte +++ /dev/null @@ -1,19 +0,0 @@ - - - - -
-

BigQuery ETL Query Network

- -
diff --git a/jobs/etl-graph/src/components/FrontMatter.svx b/jobs/etl-graph/src/components/FrontMatter.svx deleted file mode 100644 index be5fc1c8..00000000 --- a/jobs/etl-graph/src/components/FrontMatter.svx +++ /dev/null @@ -1,25 +0,0 @@ - - -{#await getLastModified() then last_modified} - -_Last updated {last_modified}_ - -{/await} - -This network represents the relationships between tables in BigQuery. It was -created by scraping the BigQuery `TABLES` and `JOBS_BY_PROJECT` tables in the -`INFORMATION_SCHEMA` dataset. - -The source can be found at [docker-etl/jobs/etl-graph][repo]. See -[NOTES.md][notes] for an overview of development. This visualizaton is powered -by [vis-network][vis-network]. - -[repo]: https://github.com/mozilla/docker-etl/tree/main/jobs/etl-graph -[notes]: https://github.com/mozilla/docker-etl/blob/main/jobs/etl-graph/README.md -[vis-network]: https://visjs.github.io/vis-network/docs/network/ \ No newline at end of file diff --git a/jobs/etl-graph/src/components/Nav.svelte b/jobs/etl-graph/src/components/Nav.svelte deleted file mode 100644 index 3ba6526d..00000000 --- a/jobs/etl-graph/src/components/Nav.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/jobs/etl-graph/src/components/Network.svelte b/jobs/etl-graph/src/components/Network.svelte deleted file mode 100644 index b57f0596..00000000 --- a/jobs/etl-graph/src/components/Network.svelte +++ /dev/null @@ -1,85 +0,0 @@ - - - - -
-{#if progress < 100} -

Loading {progress}%

-{/if} diff --git a/jobs/etl-graph/src/components/SearchBox.svelte b/jobs/etl-graph/src/components/SearchBox.svelte deleted file mode 100644 index a84549d7..00000000 --- a/jobs/etl-graph/src/components/SearchBox.svelte +++ /dev/null @@ -1,64 +0,0 @@ - - - - - search(term)} /> - - -
- {#if results} - - - - - - - - - {#each results as row} - - - - - {/each} - -
titlescore
- { - root = row.item; - redraw.set(true); - }}>{row.item.title} - {row.score.toFixed(2)}
- {/if} -
diff --git a/jobs/etl-graph/src/components/Summary.svelte b/jobs/etl-graph/src/components/Summary.svelte deleted file mode 100644 index d5327349..00000000 --- a/jobs/etl-graph/src/components/Summary.svelte +++ /dev/null @@ -1,102 +0,0 @@ - - -
- {#if output} -

{root.title}

- {#if nodeInfo} -

Query

-
-

Job History (last 10 runs)

-

- Run the following command in the command line to see more - information: - bq show -j {root.title.split(':')[0]}:$job_id -

-
- {:else} -

No associated query information found.

- {/if} -

References

- -

Destinations

- - {/if} -
diff --git a/jobs/etl-graph/src/main.js b/jobs/etl-graph/src/main.js deleted file mode 100644 index 5f050745..00000000 --- a/jobs/etl-graph/src/main.js +++ /dev/null @@ -1,11 +0,0 @@ -import App from "./App.svelte"; -import "codemirror/lib/codemirror.css"; -import "tabulator-tables/dist/css/tabulator_simple.min.css"; -import "bootstrap/dist/css/bootstrap.min.css"; - -const app = new App({ - target: document.body, - props: {}, -}); - -export default app; diff --git a/jobs/etl-graph/src/routes/Artifacts.svelte b/jobs/etl-graph/src/routes/Artifacts.svelte deleted file mode 100644 index b847ed5d..00000000 --- a/jobs/etl-graph/src/routes/Artifacts.svelte +++ /dev/null @@ -1,26 +0,0 @@ - - -

Artifacts

- -

Download the generated intermediate files.

- -{#if data} - -{/if} diff --git a/jobs/etl-graph/src/routes/Explorer.svelte b/jobs/etl-graph/src/routes/Explorer.svelte deleted file mode 100644 index 224e9781..00000000 --- a/jobs/etl-graph/src/routes/Explorer.svelte +++ /dev/null @@ -1,51 +0,0 @@ - - -{#if nodes && edges && data && selectedNode} -

Search Box

- - -

Network

-

- Scroll and drag to navigate the network. Each blue node represents a table, - while each yellow node represents a dataset. Selecting a node by clicking - will show summary information about the table or dataset. Double click a - node to center the network. By default, only neighboring nodes will be shown - in the sub-network. -

- - - -

Summary

- -{/if} diff --git a/jobs/etl-graph/src/routes/Routes.svelte b/jobs/etl-graph/src/routes/Routes.svelte deleted file mode 100644 index ef5caa78..00000000 --- a/jobs/etl-graph/src/routes/Routes.svelte +++ /dev/null @@ -1,24 +0,0 @@ - - - diff --git a/jobs/etl-graph/src/routes/Statistics.svelte b/jobs/etl-graph/src/routes/Statistics.svelte deleted file mode 100644 index 0f45f94a..00000000 --- a/jobs/etl-graph/src/routes/Statistics.svelte +++ /dev/null @@ -1,73 +0,0 @@ - - -

Network Statistics

-

- This page contains statistics about the network. These are generated with - NetworkX - on the query network. Nodes are tables and edges are references within - queries. -

- -{#if stats} - - - - - - - - - {#each ['number_of_nodes', 'number_of_edges', 'avg_in_degree', 'avg_out_degree', 'avg_degree', 'number_strongly_connected_components', 'number_weakly_connected_components'] as key} - - - - - {/each} - -
statisticvalue
{key}{stats[key]}
- -
-{/if} diff --git a/jobs/etl-graph/src/store.js b/jobs/etl-graph/src/store.js deleted file mode 100644 index 13a2f7de..00000000 --- a/jobs/etl-graph/src/store.js +++ /dev/null @@ -1,4 +0,0 @@ -import { writable } from "svelte/store"; - -export const redraw = writable(true); -export const pagePathname = writable(""); diff --git a/jobs/etl-graph/src/utils.js b/jobs/etl-graph/src/utils.js deleted file mode 100644 index 99aedfbd..00000000 --- a/jobs/etl-graph/src/utils.js +++ /dev/null @@ -1,73 +0,0 @@ -import { DataSet } from "vis-data/peer"; - -function getNode(data, title) { - return data.nodes.get({ - filter: (item) => item.title == title, - })[0]; -} - -// view-source:https://visjs.github.io/vis-network/examples/network/exampleApplications/loadingBar.html -function getDatasetId(name) { - return name.split(".")[0]; -} - -function transform(edges, includeDatasetNodes = false) { - let nodes = new Set(); - for (let i = 0; i < edges.length; i++) { - nodes.add(edges[i].destination_table); - nodes.add(edges[i].referenced_table); - } - // datasets are nodes too now, but assigned to a different group - let datasets = new Set(); - nodes.forEach((name) => { - datasets.add(getDatasetId(name)); - }); - - // check for intersection, which will break network visualization - let intersect = new Set([...nodes].filter((n) => datasets.has(n))); - if (intersect.size > 0) { - console.log("intersection between nodes and datasets found"); - console.log(intersect); - } - - let nodeMap = new Map([...nodes, ...datasets].map((el, idx) => [el, idx])); - return { - nodes: new DataSet( - [...nodes] - .map((el) => ({ - id: nodeMap.get(el), - // we show the name without the project prefix to reduce clutter - label: el.split(":")[1], - group: 0, - title: el, - })) - .concat( - includeDatasetNodes - ? [...datasets].map((el) => ({ - id: nodeMap.get(el), - label: el, - group: 1, - title: el, - })) - : [] - ) - ), - edges: new DataSet( - edges - .map((el) => ({ - from: nodeMap.get(el.referenced_table), - to: nodeMap.get(el.destination_table), - })) - .concat( - includeDatasetNodes - ? [...nodes].map((el) => ({ - from: nodeMap.get(getDatasetId(el)), - to: nodeMap.get(el), - })) - : [] - ) - ), - }; -} - -export { transform, getNode }; From c37256837a1239de4127446624a03a75b4ba9386 Mon Sep 17 00:00:00 2001 From: Wesley Dawson Date: Tue, 18 Oct 2022 15:24:47 -0700 Subject: [PATCH 2/2] Fix docker-etl build --- requirements.in | 1 + requirements.txt | 108 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 35 deletions(-) diff --git a/requirements.in b/requirements.in index 17ec060a..78a21da7 100644 --- a/requirements.in +++ b/requirements.in @@ -1,6 +1,7 @@ click==8.0.4 importlib-metadata==4.11.3 Jinja2==2.11.3 +markupsafe==2.0.1 # https://github.com/aws/aws-sam-cli/issues/3661#issuecomment-1266400556 pytest==6.0.2 pytest-black==0.3.11 pytest-flake8==1.0.6 diff --git a/requirements.txt b/requirements.txt index c04c07e7..1ae7faed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -37,41 +37,79 @@ jinja2==2.11.3 \ --hash=sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419 \ --hash=sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6 # via -r requirements.in -markupsafe==1.1.1 \ - --hash=sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473 \ - --hash=sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161 \ - --hash=sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235 \ - --hash=sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5 \ - --hash=sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42 \ - --hash=sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff \ - --hash=sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b \ - --hash=sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1 \ - --hash=sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e \ - --hash=sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183 \ - --hash=sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66 \ - --hash=sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b \ - --hash=sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1 \ - --hash=sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15 \ - --hash=sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1 \ - --hash=sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e \ - --hash=sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b \ - --hash=sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905 \ - --hash=sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735 \ - --hash=sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d \ - --hash=sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e \ - --hash=sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d \ - --hash=sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c \ - --hash=sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21 \ - --hash=sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2 \ - --hash=sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5 \ - --hash=sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b \ - --hash=sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6 \ - --hash=sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f \ - --hash=sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f \ - --hash=sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2 \ - --hash=sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7 \ - --hash=sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be - # via jinja2 +markupsafe==2.0.1 \ + --hash=sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298 \ + --hash=sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64 \ + --hash=sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b \ + --hash=sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194 \ + --hash=sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567 \ + --hash=sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff \ + --hash=sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724 \ + --hash=sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74 \ + --hash=sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646 \ + --hash=sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35 \ + --hash=sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6 \ + --hash=sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a \ + --hash=sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6 \ + --hash=sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad \ + --hash=sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26 \ + --hash=sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38 \ + --hash=sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac \ + --hash=sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7 \ + --hash=sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6 \ + --hash=sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047 \ + --hash=sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75 \ + --hash=sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f \ + --hash=sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b \ + --hash=sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135 \ + --hash=sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8 \ + --hash=sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a \ + --hash=sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a \ + --hash=sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1 \ + --hash=sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9 \ + --hash=sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864 \ + --hash=sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914 \ + --hash=sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee \ + --hash=sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f \ + --hash=sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18 \ + --hash=sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8 \ + --hash=sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2 \ + --hash=sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d \ + --hash=sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b \ + --hash=sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b \ + --hash=sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86 \ + --hash=sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6 \ + --hash=sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f \ + --hash=sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb \ + --hash=sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833 \ + --hash=sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28 \ + --hash=sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e \ + --hash=sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415 \ + --hash=sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902 \ + --hash=sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f \ + --hash=sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d \ + --hash=sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9 \ + --hash=sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d \ + --hash=sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145 \ + --hash=sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066 \ + --hash=sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c \ + --hash=sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1 \ + --hash=sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a \ + --hash=sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207 \ + --hash=sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f \ + --hash=sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53 \ + --hash=sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd \ + --hash=sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134 \ + --hash=sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85 \ + --hash=sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9 \ + --hash=sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5 \ + --hash=sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94 \ + --hash=sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509 \ + --hash=sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51 \ + --hash=sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872 + # via + # -r requirements.in + # jinja2 mccabe==0.6.1 \ --hash=sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42 \ --hash=sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f