├── LICENSE ├── README.md ├── docs └── architecture.png ├── infra ├── .gitignore ├── Pulumi.yaml ├── S3ServiceAccount.ts ├── TraefikRoute.ts ├── index.ts ├── package-lock.json ├── package.json └── tsconfig.json └── model-template ├── cookiecutter.json └── {{cookiecutter.project_slug}} ├── .dockerignore ├── .github └── workflows │ └── deploy.yml ├── .gitignore ├── Dockerfile ├── Makefile ├── README.rst ├── data ├── .dvc │ ├── .gitignore │ ├── config │ └── plots │ │ ├── confusion.json │ │ ├── confusion_normalized.json │ │ ├── default.json │ │ ├── linear.json │ │ ├── scatter.json │ │ └── smooth.json ├── .dvcignore ├── .gitignore └── iris.csv.dvc ├── infra ├── .gitignore ├── Pulumi.yaml ├── TraefikRoute.ts ├── index.ts ├── package-lock.json ├── package.json └── tsconfig.json ├── poetry.lock ├── pyproject.toml ├── src └── {{cookiecutter.module_name}} │ ├── __init__.py │ ├── serving │ ├── EXAMPLES.md │ ├── __init__.py │ └── __main__.py │ └── training │ ├── __init__.py │ └── train.py └── tests ├── __init__.py └── test_{{cookiecutter.module_name}}.py /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021 Aporia 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ML Platform Workshop 2 | 3 | This repo contains example code for a (very basic) ML platform. 4 | 5 | * The **model-template** directory contains an example for a Cookiecutter-based template that data scientists can clone to start a new project. 6 | * The **infra** directory contains Pulumi code that spins up the shared infrastructure of the ML platform, such as Kubernetes, MLFlow, etc. 7 | 8 |

Made with :heart: by Aporia

9 | 10 | ## The YouTube Video 11 | 12 | [![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/s8Jj9gzQ3xA/0.jpg)](https://www.youtube.com/watch?v=s8Jj9gzQ3xA) 13 | 14 | ## Why? 15 | 16 | As data science teams become more mature with models reaching actual production, the need for a proper infrastructure becomes crucial. Leading companies in the field with massive engineering teams like Uber, Netflix and Airbnb had created multiple solutions for their infrastructure and named the combination of them as “ML Platform”. 17 | 18 | We hope this repo can help you get started with building your own ML platform ❤️ 19 | 20 | ## Architecture 21 | 22 | 23 | 24 | ### Based on the following projects: 25 | * [FastAPI](https://fastapi.tiangolo.com/) - for model serving 26 | * [MLFlow](https://www.mlflow.org/) - for experiment tracking 27 | * [DVC](https://dvc.org/) - for data versioning 28 | * [Cookiecutter](https://cookiecutter.readthedocs.io/) - for the model template 29 | * [Pulumi](https://www.pulumi.com/) - Infrastructure as Code 30 | * [GitHub Actions](https://github.com/features/actions) - for CI/CD 31 | * [Traefik](https://traefik.io/) - API gateway 32 | * [Poetry](https://python-poetry.org/) - Python dependency management 33 | 34 | When building your own ML platform, do not take these tools for granted! [Check out alternatives](https://mlops.toys) and find the best tools that solve each one of your problems. 35 | 36 | 37 | ## What's missing from this? 38 | 39 | Well... a lot actually. Here's a partial list: 40 | 41 | * HTTPS & Authentication 42 | * Environments (staging, production) 43 | * Common library for preprocessing, postprocessing, etc 44 | * Model input & validation 45 | * Training orchestration 46 | * and probably much more! 47 | 48 | We would love your help! 49 | -------------------------------------------------------------------------------- /docs/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aporia-ai/mlplatform-workshop/268141ed1d2d6c3b18c743680945bda92265cef1/docs/architecture.png -------------------------------------------------------------------------------- /infra/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /infra/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: mlplatform-infra 2 | runtime: nodejs 3 | description: Infrastructure for open ML platform 4 | -------------------------------------------------------------------------------- /infra/S3ServiceAccount.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from '@pulumi/pulumi'; 2 | import * as aws from '@pulumi/aws'; 3 | import * as k8s from '@pulumi/kubernetes'; 4 | 5 | export interface S3ServiceAccountArgs { 6 | oidcProvider: aws.iam.OpenIdConnectProvider; 7 | namespace: pulumi.Input; 8 | readOnly: pulumi.Input; 9 | } 10 | 11 | export default class S3ServiceAccount extends pulumi.ComponentResource { 12 | public /*out*/ readonly name: pulumi.Output; 13 | public /*out*/ readonly serviceAccount: pulumi.Output; 14 | public /*out*/ readonly role: pulumi.Output; 15 | 16 | constructor(name: string, args: S3ServiceAccountArgs, opts?: pulumi.ResourceOptions) { 17 | super("pkg:index:S3ServiceAccount", name, {}, opts); 18 | 19 | // Create the new IAM policy for the Service Account using the AssumeRoleWebWebIdentity action. 20 | const serviceAccountAssumeRolePolicy = pulumi 21 | .all([args.oidcProvider.url, args.oidcProvider.arn, args.namespace]) 22 | .apply(([url, arn, namespace]: string[]) => 23 | aws.iam.getPolicyDocument({ 24 | statements: [ 25 | { 26 | actions: ['sts:AssumeRoleWithWebIdentity'], 27 | conditions: [{ 28 | test: 'StringEquals', 29 | values: [`system:serviceaccount:${namespace}:${name}`], 30 | variable: `${url.replace('https://', '')}:sub`, 31 | },], 32 | effect: 'Allow', 33 | principals: [{identifiers: [arn], type: 'Federated'}], 34 | }, 35 | ], 36 | }) 37 | ); 38 | 39 | // Create a new IAM role that assumes the AssumeRoleWebWebIdentity policy. 40 | const serviceAccountRole = new aws.iam.Role(name, { 41 | assumeRolePolicy: serviceAccountAssumeRolePolicy.json, 42 | }); 43 | 44 | // Attach the IAM role to an AWS S3 access policy. 45 | new aws.iam.RolePolicyAttachment(name, { 46 | policyArn: args.readOnly ? 47 | 'arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess' : 48 | 'arn:aws:iam::aws:policy/AmazonS3FullAccess', 49 | role: serviceAccountRole, 50 | }); 51 | 52 | // Create a Service Account with the IAM role annotated to use with the Pod. 53 | this.serviceAccount = pulumi.output(new k8s.core.v1.ServiceAccount(name, { 54 | metadata: { 55 | namespace: args.namespace, 56 | name, 57 | annotations: { 58 | 'eks.amazonaws.com/role-arn': serviceAccountRole.arn, 59 | }, 60 | }, 61 | }, { provider: opts?.provider })); 62 | 63 | this.name = pulumi.output(this.serviceAccount.metadata.name); 64 | this.role = pulumi.output(serviceAccountRole); 65 | 66 | super.registerOutputs({ 67 | name: this.serviceAccount.metadata.name, 68 | serviceAccount: this.serviceAccount, 69 | role: serviceAccountRole, 70 | }); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /infra/TraefikRoute.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from '@pulumi/pulumi'; 2 | import * as k8s from '@pulumi/kubernetes'; 3 | 4 | export interface TraefikRouteArgs { 5 | namespace: pulumi.Input; 6 | prefix: pulumi.Input; 7 | service: pulumi.Input|string; 8 | stripPrefix?: pulumi.Input|undefined; 9 | port?: pulumi.Input|undefined; 10 | } 11 | 12 | export default class TraefikRoute extends pulumi.ComponentResource { 13 | constructor(name: string, args: TraefikRouteArgs, opts?: pulumi.ResourceOptions) { 14 | super("pkg:index:TraefikRoute", name, {}, opts); 15 | 16 | const middlewares = [] 17 | 18 | // Remove trailing / 19 | const trailingSlashMiddleware = new k8s.apiextensions.CustomResource(`${name}-trailing-slash`, { 20 | apiVersion: 'traefik.containo.us/v1alpha1', 21 | kind: 'Middleware', 22 | metadata: { namespace: args.namespace }, 23 | spec: { 24 | redirectRegex: { 25 | regex: `^.*\\${args.prefix}$`, 26 | replacement: `${args.prefix}/`, 27 | permanent: false, 28 | }, 29 | }, 30 | }, { provider: opts?.provider }); 31 | 32 | middlewares.push({ name: trailingSlashMiddleware.metadata.name }); 33 | 34 | // Strip prefix 35 | if (args.stripPrefix || args.stripPrefix === undefined) { 36 | const stripPrefixMiddleware = new k8s.apiextensions.CustomResource(`${name}-strip-prefix`, { 37 | apiVersion: 'traefik.containo.us/v1alpha1', 38 | kind: 'Middleware', 39 | metadata: { namespace: args.namespace }, 40 | spec: { 41 | stripPrefix: { 42 | prefixes: [args.prefix], 43 | }, 44 | }, 45 | }, { provider: opts?.provider }); 46 | 47 | middlewares.push({ name: stripPrefixMiddleware.metadata.name }); 48 | } 49 | 50 | new k8s.apiextensions.CustomResource(`${name}-ingress-route`, { 51 | apiVersion: 'traefik.containo.us/v1alpha1', 52 | kind: 'IngressRoute', 53 | metadata: { namespace: args.namespace }, 54 | spec: { 55 | entryPoints: ['web'], 56 | routes: [{ 57 | match: `PathPrefix(\`${args.prefix}\`)`, 58 | kind: 'Rule', 59 | middlewares, 60 | services: [{ 61 | name: typeof args.service === "string" ? args.service : pulumi.output(args.service).metadata.name, 62 | port: args.port ? args.port : 63 | (typeof args.service !== "string" ? pulumi.output(args.service).spec.ports[0].port : 80), 64 | }], 65 | }] 66 | }, 67 | }, { provider: opts?.provider }); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /infra/index.ts: -------------------------------------------------------------------------------- 1 | import * as aws from '@pulumi/aws'; 2 | import * as eks from '@pulumi/eks'; 3 | import * as k8s from '@pulumi/kubernetes'; 4 | import * as random from '@pulumi/random'; 5 | import S3ServiceAccount from './S3ServiceAccount'; 6 | import TraefikRoute from './TraefikRoute'; 7 | 8 | 9 | // Create a Kubernetes cluster. 10 | const cluster = new eks.Cluster('mlplatform-eks', { 11 | createOidcProvider: true, 12 | }); 13 | 14 | 15 | // Install Traefik 16 | const traefik = new k8s.helm.v3.Chart('traefik', { 17 | chart: 'traefik', 18 | fetchOpts: { repo: 'https://containous.github.io/traefik-helm-chart' }, 19 | }, { provider: cluster.provider }) 20 | 21 | 22 | 23 | // Create PostgreSQL database for MLFlow - this will save model metadata 24 | const dbPassword = new random.RandomPassword('mlplatform-db-password', { length: 16, special: false }); 25 | const db = new aws.rds.Instance('mlflow-db', { 26 | allocatedStorage: 10, 27 | engine: "postgres", 28 | engineVersion: "11.10", 29 | instanceClass: "db.t3.medium", 30 | name: "mlflow", 31 | password: dbPassword.result, 32 | skipFinalSnapshot: true, 33 | vpcSecurityGroupIds: [cluster.clusterSecurityGroup.id, cluster.nodeSecurityGroup.id], 34 | username: "postgres", 35 | }); 36 | 37 | 38 | // Create S3 bucket for MLFlow 39 | const mlflowBucket = new aws.s3.Bucket("mlflow-bucket", { 40 | acl: "public-read-write", 41 | }); 42 | 43 | 44 | // Create S3 bucket for DVC 45 | const dvcBucket = new aws.s3.Bucket("dvc-bucket", { 46 | acl: "public-read-write", 47 | }); 48 | 49 | 50 | // Install MLFlow 51 | const mlflowNamespace = new k8s.core.v1.Namespace('mlflow-namespace', { 52 | metadata: { name: 'mlflow' }, 53 | }, { provider: cluster.provider }); 54 | 55 | const mlflowServiceAccount = new S3ServiceAccount('mlflow-service-account', { 56 | namespace: mlflowNamespace.metadata.name, 57 | oidcProvider: cluster.core.oidcProvider!, 58 | readOnly: false, 59 | }, { provider: cluster.provider }); 60 | 61 | const mlflow = new k8s.helm.v3.Chart("mlflow", { 62 | chart: "mlflow", 63 | namespace: mlflowNamespace.metadata.name, 64 | values: { 65 | "backendStore": { 66 | "postgres": { 67 | "username": db.username, 68 | "password": db.password, 69 | "host": db.address, 70 | "port": db.port, 71 | "database": "mlflow" 72 | } 73 | }, 74 | "defaultArtifactRoot": mlflowBucket.bucket.apply((bucketName: string) => `s3://${bucketName}`), 75 | "serviceAccount": { 76 | "create": false, 77 | "name": mlflowServiceAccount.name, 78 | } 79 | }, 80 | fetchOpts: { repo: "https://larribas.me/helm-charts" }, 81 | }, { provider: cluster.provider }); 82 | 83 | 84 | // Expose MLFlow in Traefik as /mlflow 85 | new TraefikRoute('mlflow', { 86 | prefix: '/mlflow', 87 | service: mlflow.getResource('v1/Service', 'mlflow', 'mlflow'), 88 | namespace: mlflowNamespace.metadata.name, 89 | }, { provider: cluster.provider, dependsOn: [mlflow] }); 90 | 91 | 92 | // Service account for models with read only access to models 93 | const modelsServiceAccount = new S3ServiceAccount('models-service-account', { 94 | namespace: 'default', 95 | oidcProvider: cluster.core.oidcProvider!, 96 | readOnly: true, 97 | }, { provider: cluster.provider }); 98 | 99 | 100 | // Set ml.mycompany.com DNS record in Route53 101 | new aws.route53.Record("record", { 102 | zoneId: "", 103 | name: "ml.mycompany.com", 104 | type: "CNAME", 105 | ttl: 300, 106 | records: [traefik.getResource('v1/Service', 'traefik').status.loadBalancer.ingress[0].hostname], 107 | }); 108 | 109 | 110 | export const kubeconfig = cluster.kubeconfig; 111 | export const mlflowTrackingURI = `http://ml.mycompany.com/mlflow`; 112 | export const dvcBucketURI = dvcBucket.bucket.apply((bucketName: string) => `s3://${bucketName}`); 113 | export const modelsServiceAccountName = modelsServiceAccount.name; 114 | -------------------------------------------------------------------------------- /infra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mlplatform-infra", 3 | "devDependencies": { 4 | "@types/node": "^14.14.41" 5 | }, 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/awsx": "^0.30.0", 9 | "@pulumi/eks": "^0.30.0", 10 | "@pulumi/kubernetes": "^3.0.0", 11 | "@pulumi/pulumi": "^3.0.0", 12 | "@pulumi/random": "^4.0.0" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /infra/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "outDir": "bin", 5 | "target": "es2016", 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "sourceMap": true, 9 | "experimentalDecorators": true, 10 | "pretty": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true 14 | }, 15 | "files": [ 16 | "index.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /model-template/cookiecutter.json: -------------------------------------------------------------------------------- 1 | { 2 | "full_name": "Alon Gubkin", 3 | "email": "alon@aporia.com", 4 | "project_name": "My Model", 5 | "project_slug": "{{ cookiecutter.project_name.lower().replace(' ', '-') }}", 6 | "module_name": "{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}", 7 | "project_short_description": "My awesome model!", 8 | "version": "0.1.0" 9 | } 10 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .cache 3 | __pycache__ 4 | node_modules 5 | data 6 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | deploy: 8 | runs-on: ubuntu-20.04 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@master 12 | 13 | - name: Install dependencies 14 | run: make install-deps 15 | 16 | - name: Deploy 17 | run: make deploy 18 | env: 19 | AWS_ACCESS_KEY_ID: {% raw %}${{ secrets.AWS_ACCESS_KEY_ID }}{% endraw %} 20 | AWS_SECRET_ACCESS_KEY: {% raw %}${{ secrets.AWS_SECRET_ACCESS_KEY }}{% endraw %} 21 | AWS_REGION: {% raw %}${{ secrets.AWS_REGION }}{% endraw %} 22 | AWS_ECR_ACCOUNT_URL: {% raw %}${{ secrets.AWS_ECR_ACCOUNT_URL }}{% endraw %} 23 | PULUMI_ACCESS_TOKEN: {% raw %}${{ secrets.PULUMI_ACCESS_TOKEN }}{% endraw %} 24 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | 132 | mlruns -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | WORKDIR /{{cookiecutter.project_slug}} 3 | STOPSIGNAL SIGINT 4 | 5 | ENV LISTEN_PORT 80 6 | 7 | # System dependencies 8 | RUN apt update && apt install -y libgomp1 9 | RUN pip3 install poetry 10 | 11 | # Project dependencies 12 | COPY poetry.lock pyproject.toml ./ 13 | 14 | RUN poetry config virtualenvs.create false 15 | RUN poetry install --no-interaction --no-ansi --no-dev 16 | 17 | COPY . . 18 | 19 | WORKDIR /{{cookiecutter.project_slug}}/src 20 | ENTRYPOINT uvicorn {{cookiecutter.module_name}}.serving.__main__:app --host 0.0.0.0 --port $LISTEN_PORT --workers 2 21 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | STACK_NAME=dev5 4 | BASE_STACK_NAME=mlplatform-infra/dev 5 | PULUMI_CMD=pulumi --non-interactive --stack $(STACK_NAME) --cwd infra/ 6 | 7 | install-deps: 8 | curl -fsSL https://get.pulumi.com | sh 9 | npm install -C infra/ 10 | 11 | sudo pip3 install poetry --upgrade 12 | poetry install 13 | 14 | train: 15 | poetry run train 16 | 17 | dvc-pull: 18 | poetry run dvc --cd data/ pull 19 | 20 | deploy: dvc-pull 21 | $(PULUMI_CMD) stack init $(STACK_NAME) || true 22 | $(PULUMI_CMD) config set aws:region $(AWS_REGION) 23 | $(PULUMI_CMD) config set baseStackName $(BASE_STACK_NAME) 24 | $(PULUMI_CMD) config set runID $(shell poetry run train | awk '/Run ID/{print $$NF}') 25 | $(PULUMI_CMD) up --yes --skip-preview 26 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/README.rst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aporia-ai/mlplatform-workshop/268141ed1d2d6c3b18c743680945bda92265cef1/model-template/{{cookiecutter.project_slug}}/README.rst -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvc/.gitignore: -------------------------------------------------------------------------------- 1 | /config.local 2 | /tmp 3 | /cache 4 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvc/config: -------------------------------------------------------------------------------- 1 | [core] 2 | remote = s3 3 | ['remote "s3"'] 4 | url = s3://dvc-bucket-511118e 5 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvc/plots/confusion.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://vega.github.io/schema/vega-lite/v4.json", 3 | "data": { 4 | "values": "" 5 | }, 6 | "title": "", 7 | "facet": { 8 | "field": "rev", 9 | "type": "nominal" 10 | }, 11 | "spec": { 12 | "transform": [ 13 | { 14 | "aggregate": [ 15 | { 16 | "op": "count", 17 | "as": "xy_count" 18 | } 19 | ], 20 | "groupby": [ 21 | "", 22 | "" 23 | ] 24 | }, 25 | { 26 | "impute": "xy_count", 27 | "groupby": [ 28 | "rev", 29 | "" 30 | ], 31 | "key": "", 32 | "value": 0 33 | }, 34 | { 35 | "impute": "xy_count", 36 | "groupby": [ 37 | "rev", 38 | "" 39 | ], 40 | "key": "", 41 | "value": 0 42 | }, 43 | { 44 | "joinaggregate": [ 45 | { 46 | "op": "max", 47 | "field": "xy_count", 48 | "as": "max_count" 49 | } 50 | ], 51 | "groupby": [] 52 | }, 53 | { 54 | "calculate": "datum.xy_count / datum.max_count", 55 | "as": "percent_of_max" 56 | } 57 | ], 58 | "encoding": { 59 | "x": { 60 | "field": "", 61 | "type": "nominal", 62 | "sort": "ascending", 63 | "title": "" 64 | }, 65 | "y": { 66 | "field": "", 67 | "type": "nominal", 68 | "sort": "ascending", 69 | "title": "" 70 | } 71 | }, 72 | "layer": [ 73 | { 74 | "mark": "rect", 75 | "width": 300, 76 | "height": 300, 77 | "encoding": { 78 | "color": { 79 | "field": "xy_count", 80 | "type": "quantitative", 81 | "title": "", 82 | "scale": { 83 | "domainMin": 0, 84 | "nice": true 85 | } 86 | } 87 | } 88 | }, 89 | { 90 | "mark": "text", 91 | "encoding": { 92 | "text": { 93 | "field": "xy_count", 94 | "type": "quantitative" 95 | }, 96 | "color": { 97 | "condition": { 98 | "test": "datum.percent_of_max > 0.5", 99 | "value": "white" 100 | }, 101 | "value": "black" 102 | } 103 | } 104 | } 105 | ] 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvc/plots/confusion_normalized.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://vega.github.io/schema/vega-lite/v4.json", 3 | "data": { 4 | "values": "" 5 | }, 6 | "title": "", 7 | "facet": { 8 | "field": "rev", 9 | "type": "nominal" 10 | }, 11 | "spec": { 12 | "transform": [ 13 | { 14 | "aggregate": [ 15 | { 16 | "op": "count", 17 | "as": "xy_count" 18 | } 19 | ], 20 | "groupby": [ 21 | "", 22 | "" 23 | ] 24 | }, 25 | { 26 | "impute": "xy_count", 27 | "groupby": [ 28 | "rev", 29 | "" 30 | ], 31 | "key": "", 32 | "value": 0 33 | }, 34 | { 35 | "impute": "xy_count", 36 | "groupby": [ 37 | "rev", 38 | "" 39 | ], 40 | "key": "", 41 | "value": 0 42 | }, 43 | { 44 | "joinaggregate": [ 45 | { 46 | "op": "sum", 47 | "field": "xy_count", 48 | "as": "sum_y" 49 | } 50 | ], 51 | "groupby": [ 52 | "" 53 | ] 54 | }, 55 | { 56 | "calculate": "datum.xy_count / datum.sum_y", 57 | "as": "percent_of_y" 58 | } 59 | ], 60 | "encoding": { 61 | "x": { 62 | "field": "", 63 | "type": "nominal", 64 | "sort": "ascending", 65 | "title": "" 66 | }, 67 | "y": { 68 | "field": "", 69 | "type": "nominal", 70 | "sort": "ascending", 71 | "title": "" 72 | } 73 | }, 74 | "layer": [ 75 | { 76 | "mark": "rect", 77 | "width": 300, 78 | "height": 300, 79 | "encoding": { 80 | "color": { 81 | "field": "percent_of_y", 82 | "type": "quantitative", 83 | "title": "", 84 | "scale": { 85 | "domain": [ 86 | 0, 87 | 1 88 | ] 89 | } 90 | } 91 | } 92 | }, 93 | { 94 | "mark": "text", 95 | "encoding": { 96 | "text": { 97 | "field": "percent_of_y", 98 | "type": "quantitative", 99 | "format": ".2f" 100 | }, 101 | "color": { 102 | "condition": { 103 | "test": "datum.percent_of_y > 0.5", 104 | "value": "white" 105 | }, 106 | "value": "black" 107 | } 108 | } 109 | } 110 | ] 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvc/plots/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://vega.github.io/schema/vega-lite/v4.json", 3 | "data": { 4 | "values": "" 5 | }, 6 | "title": "", 7 | "width": 300, 8 | "height": 300, 9 | "mark": { 10 | "type": "line" 11 | }, 12 | "encoding": { 13 | "x": { 14 | "field": "", 15 | "type": "quantitative", 16 | "title": "" 17 | }, 18 | "y": { 19 | "field": "", 20 | "type": "quantitative", 21 | "title": "", 22 | "scale": { 23 | "zero": false 24 | } 25 | }, 26 | "color": { 27 | "field": "rev", 28 | "type": "nominal" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvc/plots/linear.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://vega.github.io/schema/vega-lite/v4.json", 3 | "data": { 4 | "values": "" 5 | }, 6 | "title": "", 7 | "width": 300, 8 | "height": 300, 9 | "layer": [ 10 | { 11 | "encoding": { 12 | "x": { 13 | "field": "", 14 | "type": "quantitative", 15 | "title": "" 16 | }, 17 | "y": { 18 | "field": "", 19 | "type": "quantitative", 20 | "title": "", 21 | "scale": { 22 | "zero": false 23 | } 24 | }, 25 | "color": { 26 | "field": "rev", 27 | "type": "nominal" 28 | } 29 | }, 30 | "layer": [ 31 | { 32 | "mark": "line" 33 | }, 34 | { 35 | "selection": { 36 | "label": { 37 | "type": "single", 38 | "nearest": true, 39 | "on": "mouseover", 40 | "encodings": [ 41 | "x" 42 | ], 43 | "empty": "none", 44 | "clear": "mouseout" 45 | } 46 | }, 47 | "mark": "point", 48 | "encoding": { 49 | "opacity": { 50 | "condition": { 51 | "selection": "label", 52 | "value": 1 53 | }, 54 | "value": 0 55 | } 56 | } 57 | } 58 | ] 59 | }, 60 | { 61 | "transform": [ 62 | { 63 | "filter": { 64 | "selection": "label" 65 | } 66 | } 67 | ], 68 | "layer": [ 69 | { 70 | "mark": { 71 | "type": "rule", 72 | "color": "gray" 73 | }, 74 | "encoding": { 75 | "x": { 76 | "field": "", 77 | "type": "quantitative" 78 | } 79 | } 80 | }, 81 | { 82 | "encoding": { 83 | "text": { 84 | "type": "quantitative", 85 | "field": "" 86 | }, 87 | "x": { 88 | "field": "", 89 | "type": "quantitative" 90 | }, 91 | "y": { 92 | "field": "", 93 | "type": "quantitative" 94 | } 95 | }, 96 | "layer": [ 97 | { 98 | "mark": { 99 | "type": "text", 100 | "align": "left", 101 | "dx": 5, 102 | "dy": -5 103 | }, 104 | "encoding": { 105 | "color": { 106 | "type": "nominal", 107 | "field": "rev" 108 | } 109 | } 110 | } 111 | ] 112 | } 113 | ] 114 | } 115 | ] 116 | } 117 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvc/plots/scatter.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://vega.github.io/schema/vega-lite/v4.json", 3 | "data": { 4 | "values": "" 5 | }, 6 | "title": "", 7 | "width": 300, 8 | "height": 300, 9 | "layer": [ 10 | { 11 | "encoding": { 12 | "x": { 13 | "field": "", 14 | "type": "quantitative", 15 | "title": "" 16 | }, 17 | "y": { 18 | "field": "", 19 | "type": "quantitative", 20 | "title": "", 21 | "scale": { 22 | "zero": false 23 | } 24 | }, 25 | "color": { 26 | "field": "rev", 27 | "type": "nominal" 28 | } 29 | }, 30 | "layer": [ 31 | { 32 | "mark": "point" 33 | }, 34 | { 35 | "selection": { 36 | "label": { 37 | "type": "single", 38 | "nearest": true, 39 | "on": "mouseover", 40 | "encodings": [ 41 | "x" 42 | ], 43 | "empty": "none", 44 | "clear": "mouseout" 45 | } 46 | }, 47 | "mark": "point", 48 | "encoding": { 49 | "opacity": { 50 | "condition": { 51 | "selection": "label", 52 | "value": 1 53 | }, 54 | "value": 0 55 | } 56 | } 57 | } 58 | ] 59 | }, 60 | { 61 | "transform": [ 62 | { 63 | "filter": { 64 | "selection": "label" 65 | } 66 | } 67 | ], 68 | "layer": [ 69 | { 70 | "encoding": { 71 | "text": { 72 | "type": "quantitative", 73 | "field": "" 74 | }, 75 | "x": { 76 | "field": "", 77 | "type": "quantitative" 78 | }, 79 | "y": { 80 | "field": "", 81 | "type": "quantitative" 82 | } 83 | }, 84 | "layer": [ 85 | { 86 | "mark": { 87 | "type": "text", 88 | "align": "left", 89 | "dx": 5, 90 | "dy": -5 91 | }, 92 | "encoding": { 93 | "color": { 94 | "type": "nominal", 95 | "field": "rev" 96 | } 97 | } 98 | } 99 | ] 100 | } 101 | ] 102 | } 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvc/plots/smooth.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://vega.github.io/schema/vega-lite/v4.json", 3 | "data": { 4 | "values": "" 5 | }, 6 | "title": "", 7 | "mark": { 8 | "type": "line" 9 | }, 10 | "encoding": { 11 | "x": { 12 | "field": "", 13 | "type": "quantitative", 14 | "title": "" 15 | }, 16 | "y": { 17 | "field": "", 18 | "type": "quantitative", 19 | "title": "", 20 | "scale": { 21 | "zero": false 22 | } 23 | }, 24 | "color": { 25 | "field": "rev", 26 | "type": "nominal" 27 | } 28 | }, 29 | "transform": [ 30 | { 31 | "loess": "", 32 | "on": "", 33 | "groupby": [ 34 | "rev" 35 | ], 36 | "bandwidth": 0.3 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.dvcignore: -------------------------------------------------------------------------------- 1 | # Add patterns of files dvc should ignore, which could improve 2 | # the performance. Learn more at 3 | # https://dvc.org/doc/user-guide/dvcignore 4 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/.gitignore: -------------------------------------------------------------------------------- 1 | /iris.csv 2 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/data/iris.csv.dvc: -------------------------------------------------------------------------------- 1 | outs: 2 | - md5: 341a3b5244f213282b7b0920b729c592 3 | size: 4125 4 | path: iris.csv 5 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/infra/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | /node_modules/ 3 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/infra/Pulumi.yaml: -------------------------------------------------------------------------------- 1 | name: {{cookiecutter.project_slug}}-infra 2 | runtime: nodejs 3 | description: Serving infrastructure for {{cookiecutter.project_slug}} 4 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/infra/TraefikRoute.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from '@pulumi/pulumi'; 2 | import * as k8s from '@pulumi/kubernetes'; 3 | 4 | export interface TraefikRouteArgs { 5 | namespace: pulumi.Input; 6 | prefix: pulumi.Input; 7 | service: pulumi.Input; 8 | } 9 | 10 | export default class TraefikRoute extends pulumi.ComponentResource { 11 | constructor(name: string, args: TraefikRouteArgs, opts?: pulumi.ResourceOptions) { 12 | super("pkg:index:TraefikRoute", name, {}, opts); 13 | 14 | const trailingSlashMiddleware = new k8s.apiextensions.CustomResource(`${name}-trailing-slash`, { 15 | apiVersion: 'traefik.containo.us/v1alpha1', 16 | kind: 'Middleware', 17 | metadata: { namespace: args.namespace }, 18 | spec: { 19 | redirectRegex: { 20 | regex: `^.*\\${args.prefix}$`, 21 | replacement: `${args.prefix}/`, 22 | permanent: false, 23 | }, 24 | }, 25 | }, { provider: opts?.provider }); 26 | 27 | const stripPrefixMiddleware = new k8s.apiextensions.CustomResource(`${name}-strip-prefix`, { 28 | apiVersion: 'traefik.containo.us/v1alpha1', 29 | kind: 'Middleware', 30 | metadata: { namespace: args.namespace }, 31 | spec: { 32 | stripPrefix: { 33 | prefixes: [args.prefix], 34 | }, 35 | }, 36 | }, { provider: opts?.provider }); 37 | 38 | new k8s.apiextensions.CustomResource(`${name}-ingress-route`, { 39 | apiVersion: 'traefik.containo.us/v1alpha1', 40 | kind: 'IngressRoute', 41 | metadata: { namespace: args.namespace }, 42 | spec: { 43 | entryPoints: ['web'], 44 | routes: [{ 45 | match: `PathPrefix(\`${args.prefix}\`)`, 46 | kind: 'Rule', 47 | middlewares: [ 48 | { name: trailingSlashMiddleware.metadata.name }, 49 | { name: stripPrefixMiddleware.metadata.name }, 50 | ], 51 | services: [{ 52 | name: pulumi.output(args.service).metadata.name, 53 | port: pulumi.output(args.service).spec.ports[0].port, 54 | }], 55 | }] 56 | }, 57 | }, { provider: opts?.provider, dependsOn: [trailingSlashMiddleware, stripPrefixMiddleware] }); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/infra/index.ts: -------------------------------------------------------------------------------- 1 | import * as pulumi from '@pulumi/pulumi'; 2 | import * as awsx from '@pulumi/awsx'; 3 | import * as k8s from '@pulumi/kubernetes'; 4 | import * as kx from '@pulumi/kubernetesx'; 5 | import TraefikRoute from './TraefikRoute'; 6 | 7 | const config = new pulumi.Config(); 8 | const baseStack = new pulumi.StackReference(config.require('baseStackName')) 9 | 10 | const provider = new k8s.Provider('provider', { 11 | kubeconfig: baseStack.requireOutput('kubeconfig'), 12 | }) 13 | 14 | const image = awsx.ecr.buildAndPushImage('{{cookiecutter.project_slug}}-image', { 15 | context: '../', 16 | }); 17 | 18 | const podBuilder = new kx.PodBuilder({ 19 | containers: [{ 20 | image: image.imageValue, 21 | ports: { http: 80 }, 22 | env: { 23 | 'LISTEN_PORT': '80', 24 | 'MLFLOW_TRACKING_URI': baseStack.requireOutput('mlflowTrackingURI'), 25 | 'MLFLOW_RUN_ID': config.require('runID'), 26 | } 27 | }], 28 | serviceAccountName: baseStack.requireOutput('modelsServiceAccountName'), 29 | }); 30 | 31 | const deployment = new kx.Deployment('{{cookiecutter.project_slug}}-serving', { 32 | spec: podBuilder.asDeploymentSpec({ replicas: 3 }) 33 | }, { provider }); 34 | 35 | const service = deployment.createService(); 36 | 37 | 38 | // Expose model in Traefik 39 | new TraefikRoute('{{cookiecutter.project_slug}}', { 40 | prefix: '/models/{{cookiecutter.project_slug}}', 41 | service, 42 | namespace: 'default', 43 | }, { provider, dependsOn: [service] }); 44 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/infra/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{cookiecutter.project_slug}}-infra", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "name": "{{cookiecutter.project_slug}}-infra", 8 | "dependencies": { 9 | "@pulumi/aws": "^4.0.0", 10 | "@pulumi/awsx": "^0.30.0", 11 | "@pulumi/kubernetes": "^3.3.0", 12 | "@pulumi/kubernetesx": "^0.1.6", 13 | "@pulumi/pulumi": "^3.0.0" 14 | }, 15 | "devDependencies": { 16 | "@types/node": "^10.0.0" 17 | } 18 | }, 19 | "node_modules/@grpc/grpc-js": { 20 | "version": "1.3.2", 21 | "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.3.2.tgz", 22 | "integrity": "sha512-UXepkOKCATJrhHGsxt+CGfpZy9zUn1q9mop5kfcXq1fBkTePxVNPOdnISlCbJFlCtld+pSLGyZCzr9/zVprFKA==", 23 | "dependencies": { 24 | "@types/node": ">=12.12.47" 25 | }, 26 | "engines": { 27 | "node": "^8.13.0 || >=10.10.0" 28 | } 29 | }, 30 | "node_modules/@grpc/grpc-js/node_modules/@types/node": { 31 | "version": "15.12.0", 32 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz", 33 | "integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==" 34 | }, 35 | "node_modules/@logdna/tail-file": { 36 | "version": "2.0.7", 37 | "resolved": "https://registry.npmjs.org/@logdna/tail-file/-/tail-file-2.0.7.tgz", 38 | "integrity": "sha512-ycw0OrbphtfGOnygF+J4J/kJELXifLUiQ/CSTMb9Ztqjnuq4h+Id3MEvt4FTyyyekYbzStx7TjkhqXFW6Mi9LA==", 39 | "engines": { 40 | "node": ">=10.3.0" 41 | } 42 | }, 43 | "node_modules/@protobufjs/aspromise": { 44 | "version": "1.1.2", 45 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 46 | "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" 47 | }, 48 | "node_modules/@protobufjs/base64": { 49 | "version": "1.1.2", 50 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 51 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" 52 | }, 53 | "node_modules/@protobufjs/codegen": { 54 | "version": "2.0.4", 55 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 56 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" 57 | }, 58 | "node_modules/@protobufjs/eventemitter": { 59 | "version": "1.1.0", 60 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 61 | "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" 62 | }, 63 | "node_modules/@protobufjs/fetch": { 64 | "version": "1.1.0", 65 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 66 | "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", 67 | "dependencies": { 68 | "@protobufjs/aspromise": "^1.1.1", 69 | "@protobufjs/inquire": "^1.1.0" 70 | } 71 | }, 72 | "node_modules/@protobufjs/float": { 73 | "version": "1.0.2", 74 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 75 | "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" 76 | }, 77 | "node_modules/@protobufjs/inquire": { 78 | "version": "1.1.0", 79 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 80 | "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" 81 | }, 82 | "node_modules/@protobufjs/path": { 83 | "version": "1.1.2", 84 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 85 | "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" 86 | }, 87 | "node_modules/@protobufjs/pool": { 88 | "version": "1.1.0", 89 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 90 | "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" 91 | }, 92 | "node_modules/@protobufjs/utf8": { 93 | "version": "1.1.0", 94 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 95 | "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" 96 | }, 97 | "node_modules/@pulumi/aws": { 98 | "version": "4.6.0", 99 | "resolved": "https://registry.npmjs.org/@pulumi/aws/-/aws-4.6.0.tgz", 100 | "integrity": "sha512-it0Q9FUd7v/2PgAvoXxTrTT/kQM1iwLNrxnBDabByQsGIOpp4jj4C+sexOoMH4IbKz6mwkLUaPS84QU/qDfndg==", 101 | "hasInstallScript": true, 102 | "dependencies": { 103 | "@pulumi/pulumi": "^3.0.0", 104 | "aws-sdk": "^2.0.0", 105 | "builtin-modules": "3.0.0", 106 | "mime": "^2.0.0", 107 | "read-package-tree": "^5.2.1", 108 | "resolve": "^1.7.1" 109 | } 110 | }, 111 | "node_modules/@pulumi/awsx": { 112 | "version": "0.30.0", 113 | "resolved": "https://registry.npmjs.org/@pulumi/awsx/-/awsx-0.30.0.tgz", 114 | "integrity": "sha512-QtYVDFSkZxJ/JkAxaSwms9i/tJU2rA9F/VncCN6e8D0r29C5t4eYQhmB4chsLww9AjWJPRM7CXosDJs8+gy1Zg==", 115 | "dependencies": { 116 | "@pulumi/docker": "^3.0.0", 117 | "@types/aws-lambda": "^8.10.23", 118 | "mime": "^2.0.0" 119 | }, 120 | "peerDependencies": { 121 | "@pulumi/aws": "^4.0.0", 122 | "@pulumi/pulumi": "^3.0.0" 123 | } 124 | }, 125 | "node_modules/@pulumi/docker": { 126 | "version": "3.0.0", 127 | "resolved": "https://registry.npmjs.org/@pulumi/docker/-/docker-3.0.0.tgz", 128 | "integrity": "sha512-AzPhb/ibuHBy+GGDHrY3rPJeaO5DIMqv/ABtenQdoAw8X00E3UTV+D9dDS/GRq0oJ2aDvZupIlSdrPD7eJ5jgA==", 129 | "hasInstallScript": true, 130 | "dependencies": { 131 | "@pulumi/pulumi": "^3.0.0", 132 | "semver": "^5.4.0" 133 | } 134 | }, 135 | "node_modules/@pulumi/kubernetes": { 136 | "version": "3.3.0", 137 | "resolved": "https://registry.npmjs.org/@pulumi/kubernetes/-/kubernetes-3.3.0.tgz", 138 | "integrity": "sha512-iM5qYPs6iaa7Wti/cX17mNMMpVCMWo5aaF7RKydiy+FYFY+SJ1sk0wBoVj/A0RxteIVEYU+NiFrfUMGKe4HjQw==", 139 | "hasInstallScript": true, 140 | "dependencies": { 141 | "@pulumi/pulumi": "^3.0.0", 142 | "@types/glob": "^5.0.35", 143 | "@types/node-fetch": "^2.1.4", 144 | "@types/tmp": "^0.0.33", 145 | "glob": "^7.1.2", 146 | "node-fetch": "^2.3.0", 147 | "shell-quote": "^1.6.1", 148 | "tmp": "^0.0.33" 149 | } 150 | }, 151 | "node_modules/@pulumi/kubernetesx": { 152 | "version": "0.1.6", 153 | "resolved": "https://registry.npmjs.org/@pulumi/kubernetesx/-/kubernetesx-0.1.6.tgz", 154 | "integrity": "sha512-9VL4Yi4b4aLC/obBarJuNkm86kABByUZICYPSTdV396MGZtOc066o2brsB+kWVQcVfkYVXTPrpjIkAwBXXnzGw==", 155 | "peerDependencies": { 156 | "@pulumi/kubernetes": "^3.0.0", 157 | "@pulumi/pulumi": "^3.0.0" 158 | } 159 | }, 160 | "node_modules/@pulumi/pulumi": { 161 | "version": "3.3.1", 162 | "resolved": "https://registry.npmjs.org/@pulumi/pulumi/-/pulumi-3.3.1.tgz", 163 | "integrity": "sha512-W5HBFCQUY67QaPXtDSZ6Fe/K8mB+X7tJqi2pBU6UUUMtJVndcZ5BpLkZBznu+Nq/ZmitmGVaOpUqC5yK70D98A==", 164 | "dependencies": { 165 | "@grpc/grpc-js": "^1.2.7", 166 | "@logdna/tail-file": "^2.0.6", 167 | "@pulumi/query": "^0.3.0", 168 | "google-protobuf": "^3.5.0", 169 | "js-yaml": "^3.14.0", 170 | "minimist": "^1.2.0", 171 | "normalize-package-data": "^2.4.0", 172 | "protobufjs": "^6.8.6", 173 | "read-package-tree": "^5.3.1", 174 | "require-from-string": "^2.0.1", 175 | "semver": "^6.1.0", 176 | "source-map-support": "^0.4.16", 177 | "ts-node": "^7.0.1", 178 | "typescript": "~3.7.3", 179 | "upath": "^1.1.0" 180 | }, 181 | "engines": { 182 | "node": ">=8.13.0 || >=10.10.0" 183 | } 184 | }, 185 | "node_modules/@pulumi/pulumi/node_modules/semver": { 186 | "version": "6.3.0", 187 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 188 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 189 | "bin": { 190 | "semver": "bin/semver.js" 191 | } 192 | }, 193 | "node_modules/@pulumi/query": { 194 | "version": "0.3.0", 195 | "resolved": "https://registry.npmjs.org/@pulumi/query/-/query-0.3.0.tgz", 196 | "integrity": "sha512-xfo+yLRM2zVjVEA4p23IjQWzyWl1ZhWOGobsBqRpIarzLvwNH/RAGaoehdxlhx4X92302DrpdIFgTICMN4P38w==" 197 | }, 198 | "node_modules/@types/aws-lambda": { 199 | "version": "8.10.76", 200 | "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.76.tgz", 201 | "integrity": "sha512-lCTyeRm3NWqSwDnoji0z82Pl0tsOpr1p+33AiNeidgarloWXh3wdiVRUuxEa+sY9S5YLOYGz5X3N3Zvpibvm5w==" 202 | }, 203 | "node_modules/@types/events": { 204 | "version": "3.0.0", 205 | "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", 206 | "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" 207 | }, 208 | "node_modules/@types/glob": { 209 | "version": "5.0.36", 210 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.36.tgz", 211 | "integrity": "sha512-KEzSKuP2+3oOjYYjujue6Z3Yqis5HKA1BsIC+jZ1v3lrRNdsqyNNtX0rQf6LSuI4DJJ2z5UV//zBZCcvM0xikg==", 212 | "dependencies": { 213 | "@types/events": "*", 214 | "@types/minimatch": "*", 215 | "@types/node": "*" 216 | } 217 | }, 218 | "node_modules/@types/long": { 219 | "version": "4.0.1", 220 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", 221 | "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" 222 | }, 223 | "node_modules/@types/minimatch": { 224 | "version": "3.0.4", 225 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", 226 | "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==" 227 | }, 228 | "node_modules/@types/node": { 229 | "version": "10.17.60", 230 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", 231 | "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" 232 | }, 233 | "node_modules/@types/node-fetch": { 234 | "version": "2.5.10", 235 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz", 236 | "integrity": "sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==", 237 | "dependencies": { 238 | "@types/node": "*", 239 | "form-data": "^3.0.0" 240 | } 241 | }, 242 | "node_modules/@types/tmp": { 243 | "version": "0.0.33", 244 | "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz", 245 | "integrity": "sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=" 246 | }, 247 | "node_modules/argparse": { 248 | "version": "1.0.10", 249 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 250 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 251 | "dependencies": { 252 | "sprintf-js": "~1.0.2" 253 | } 254 | }, 255 | "node_modules/arrify": { 256 | "version": "1.0.1", 257 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 258 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 259 | "engines": { 260 | "node": ">=0.10.0" 261 | } 262 | }, 263 | "node_modules/asap": { 264 | "version": "2.0.6", 265 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 266 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 267 | }, 268 | "node_modules/asynckit": { 269 | "version": "0.4.0", 270 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 271 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 272 | }, 273 | "node_modules/aws-sdk": { 274 | "version": "2.920.0", 275 | "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.920.0.tgz", 276 | "integrity": "sha512-tbMZ/Y2rRo6R6TTBODJXTiil+MXaoT6Qzotws3yvI1IWGpYxKo7N/3L06XB8ul8tCG0TigxIOY70SMICM70Ppg==", 277 | "hasInstallScript": true, 278 | "dependencies": { 279 | "buffer": "4.9.2", 280 | "events": "1.1.1", 281 | "ieee754": "1.1.13", 282 | "jmespath": "0.15.0", 283 | "querystring": "0.2.0", 284 | "sax": "1.2.1", 285 | "url": "0.10.3", 286 | "uuid": "3.3.2", 287 | "xml2js": "0.4.19" 288 | }, 289 | "engines": { 290 | "node": ">= 0.8.0" 291 | } 292 | }, 293 | "node_modules/balanced-match": { 294 | "version": "1.0.2", 295 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 296 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 297 | }, 298 | "node_modules/base64-js": { 299 | "version": "1.5.1", 300 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 301 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 302 | "funding": [ 303 | { 304 | "type": "github", 305 | "url": "https://github.com/sponsors/feross" 306 | }, 307 | { 308 | "type": "patreon", 309 | "url": "https://www.patreon.com/feross" 310 | }, 311 | { 312 | "type": "consulting", 313 | "url": "https://feross.org/support" 314 | } 315 | ] 316 | }, 317 | "node_modules/brace-expansion": { 318 | "version": "1.1.11", 319 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 320 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 321 | "dependencies": { 322 | "balanced-match": "^1.0.0", 323 | "concat-map": "0.0.1" 324 | } 325 | }, 326 | "node_modules/buffer": { 327 | "version": "4.9.2", 328 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", 329 | "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", 330 | "dependencies": { 331 | "base64-js": "^1.0.2", 332 | "ieee754": "^1.1.4", 333 | "isarray": "^1.0.0" 334 | } 335 | }, 336 | "node_modules/buffer-from": { 337 | "version": "1.1.1", 338 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 339 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 340 | }, 341 | "node_modules/builtin-modules": { 342 | "version": "3.0.0", 343 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.0.0.tgz", 344 | "integrity": "sha512-hMIeU4K2ilbXV6Uv93ZZ0Avg/M91RaKXucQ+4me2Do1txxBDyDZWCBa5bJSLqoNTRpXTLwEzIk1KmloenDDjhg==", 345 | "engines": { 346 | "node": ">=6" 347 | } 348 | }, 349 | "node_modules/call-bind": { 350 | "version": "1.0.2", 351 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 352 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 353 | "dependencies": { 354 | "function-bind": "^1.1.1", 355 | "get-intrinsic": "^1.0.2" 356 | }, 357 | "funding": { 358 | "url": "https://github.com/sponsors/ljharb" 359 | } 360 | }, 361 | "node_modules/combined-stream": { 362 | "version": "1.0.8", 363 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 364 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 365 | "dependencies": { 366 | "delayed-stream": "~1.0.0" 367 | }, 368 | "engines": { 369 | "node": ">= 0.8" 370 | } 371 | }, 372 | "node_modules/concat-map": { 373 | "version": "0.0.1", 374 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 375 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 376 | }, 377 | "node_modules/debuglog": { 378 | "version": "1.0.1", 379 | "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", 380 | "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", 381 | "engines": { 382 | "node": "*" 383 | } 384 | }, 385 | "node_modules/define-properties": { 386 | "version": "1.1.3", 387 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 388 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 389 | "dependencies": { 390 | "object-keys": "^1.0.12" 391 | }, 392 | "engines": { 393 | "node": ">= 0.4" 394 | } 395 | }, 396 | "node_modules/delayed-stream": { 397 | "version": "1.0.0", 398 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 399 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", 400 | "engines": { 401 | "node": ">=0.4.0" 402 | } 403 | }, 404 | "node_modules/dezalgo": { 405 | "version": "1.0.3", 406 | "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", 407 | "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", 408 | "dependencies": { 409 | "asap": "^2.0.0", 410 | "wrappy": "1" 411 | } 412 | }, 413 | "node_modules/diff": { 414 | "version": "3.5.0", 415 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 416 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 417 | "engines": { 418 | "node": ">=0.3.1" 419 | } 420 | }, 421 | "node_modules/es-abstract": { 422 | "version": "1.18.3", 423 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", 424 | "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", 425 | "dependencies": { 426 | "call-bind": "^1.0.2", 427 | "es-to-primitive": "^1.2.1", 428 | "function-bind": "^1.1.1", 429 | "get-intrinsic": "^1.1.1", 430 | "has": "^1.0.3", 431 | "has-symbols": "^1.0.2", 432 | "is-callable": "^1.2.3", 433 | "is-negative-zero": "^2.0.1", 434 | "is-regex": "^1.1.3", 435 | "is-string": "^1.0.6", 436 | "object-inspect": "^1.10.3", 437 | "object-keys": "^1.1.1", 438 | "object.assign": "^4.1.2", 439 | "string.prototype.trimend": "^1.0.4", 440 | "string.prototype.trimstart": "^1.0.4", 441 | "unbox-primitive": "^1.0.1" 442 | }, 443 | "engines": { 444 | "node": ">= 0.4" 445 | }, 446 | "funding": { 447 | "url": "https://github.com/sponsors/ljharb" 448 | } 449 | }, 450 | "node_modules/es-to-primitive": { 451 | "version": "1.2.1", 452 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 453 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 454 | "dependencies": { 455 | "is-callable": "^1.1.4", 456 | "is-date-object": "^1.0.1", 457 | "is-symbol": "^1.0.2" 458 | }, 459 | "engines": { 460 | "node": ">= 0.4" 461 | }, 462 | "funding": { 463 | "url": "https://github.com/sponsors/ljharb" 464 | } 465 | }, 466 | "node_modules/esprima": { 467 | "version": "4.0.1", 468 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 469 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 470 | "bin": { 471 | "esparse": "bin/esparse.js", 472 | "esvalidate": "bin/esvalidate.js" 473 | }, 474 | "engines": { 475 | "node": ">=4" 476 | } 477 | }, 478 | "node_modules/events": { 479 | "version": "1.1.1", 480 | "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", 481 | "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", 482 | "engines": { 483 | "node": ">=0.4.x" 484 | } 485 | }, 486 | "node_modules/form-data": { 487 | "version": "3.0.1", 488 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", 489 | "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", 490 | "dependencies": { 491 | "asynckit": "^0.4.0", 492 | "combined-stream": "^1.0.8", 493 | "mime-types": "^2.1.12" 494 | }, 495 | "engines": { 496 | "node": ">= 6" 497 | } 498 | }, 499 | "node_modules/fs.realpath": { 500 | "version": "1.0.0", 501 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 502 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 503 | }, 504 | "node_modules/function-bind": { 505 | "version": "1.1.1", 506 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 507 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 508 | }, 509 | "node_modules/get-intrinsic": { 510 | "version": "1.1.1", 511 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 512 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 513 | "dependencies": { 514 | "function-bind": "^1.1.1", 515 | "has": "^1.0.3", 516 | "has-symbols": "^1.0.1" 517 | }, 518 | "funding": { 519 | "url": "https://github.com/sponsors/ljharb" 520 | } 521 | }, 522 | "node_modules/glob": { 523 | "version": "7.1.7", 524 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 525 | "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 526 | "dependencies": { 527 | "fs.realpath": "^1.0.0", 528 | "inflight": "^1.0.4", 529 | "inherits": "2", 530 | "minimatch": "^3.0.4", 531 | "once": "^1.3.0", 532 | "path-is-absolute": "^1.0.0" 533 | }, 534 | "engines": { 535 | "node": "*" 536 | }, 537 | "funding": { 538 | "url": "https://github.com/sponsors/isaacs" 539 | } 540 | }, 541 | "node_modules/google-protobuf": { 542 | "version": "3.17.2", 543 | "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.17.2.tgz", 544 | "integrity": "sha512-LlFVMhSkNy6C1MakEjiwbLxq5w+V+Go+mvt2EUoysrp8gXl903ic2W/3BwzM4/WnDMJP+u7UO2efUSl/0CJMzA==" 545 | }, 546 | "node_modules/graceful-fs": { 547 | "version": "4.2.6", 548 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", 549 | "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" 550 | }, 551 | "node_modules/has": { 552 | "version": "1.0.3", 553 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 554 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 555 | "dependencies": { 556 | "function-bind": "^1.1.1" 557 | }, 558 | "engines": { 559 | "node": ">= 0.4.0" 560 | } 561 | }, 562 | "node_modules/has-bigints": { 563 | "version": "1.0.1", 564 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", 565 | "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", 566 | "funding": { 567 | "url": "https://github.com/sponsors/ljharb" 568 | } 569 | }, 570 | "node_modules/has-symbols": { 571 | "version": "1.0.2", 572 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 573 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", 574 | "engines": { 575 | "node": ">= 0.4" 576 | }, 577 | "funding": { 578 | "url": "https://github.com/sponsors/ljharb" 579 | } 580 | }, 581 | "node_modules/hosted-git-info": { 582 | "version": "2.8.9", 583 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", 584 | "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" 585 | }, 586 | "node_modules/ieee754": { 587 | "version": "1.1.13", 588 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 589 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 590 | }, 591 | "node_modules/inflight": { 592 | "version": "1.0.6", 593 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 594 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 595 | "dependencies": { 596 | "once": "^1.3.0", 597 | "wrappy": "1" 598 | } 599 | }, 600 | "node_modules/inherits": { 601 | "version": "2.0.4", 602 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 603 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 604 | }, 605 | "node_modules/is-bigint": { 606 | "version": "1.0.2", 607 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", 608 | "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", 609 | "funding": { 610 | "url": "https://github.com/sponsors/ljharb" 611 | } 612 | }, 613 | "node_modules/is-boolean-object": { 614 | "version": "1.1.1", 615 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", 616 | "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", 617 | "dependencies": { 618 | "call-bind": "^1.0.2" 619 | }, 620 | "engines": { 621 | "node": ">= 0.4" 622 | }, 623 | "funding": { 624 | "url": "https://github.com/sponsors/ljharb" 625 | } 626 | }, 627 | "node_modules/is-callable": { 628 | "version": "1.2.3", 629 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", 630 | "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", 631 | "engines": { 632 | "node": ">= 0.4" 633 | }, 634 | "funding": { 635 | "url": "https://github.com/sponsors/ljharb" 636 | } 637 | }, 638 | "node_modules/is-core-module": { 639 | "version": "2.4.0", 640 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", 641 | "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", 642 | "dependencies": { 643 | "has": "^1.0.3" 644 | }, 645 | "funding": { 646 | "url": "https://github.com/sponsors/ljharb" 647 | } 648 | }, 649 | "node_modules/is-date-object": { 650 | "version": "1.0.4", 651 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", 652 | "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", 653 | "engines": { 654 | "node": ">= 0.4" 655 | }, 656 | "funding": { 657 | "url": "https://github.com/sponsors/ljharb" 658 | } 659 | }, 660 | "node_modules/is-negative-zero": { 661 | "version": "2.0.1", 662 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", 663 | "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", 664 | "engines": { 665 | "node": ">= 0.4" 666 | }, 667 | "funding": { 668 | "url": "https://github.com/sponsors/ljharb" 669 | } 670 | }, 671 | "node_modules/is-number-object": { 672 | "version": "1.0.5", 673 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", 674 | "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", 675 | "engines": { 676 | "node": ">= 0.4" 677 | }, 678 | "funding": { 679 | "url": "https://github.com/sponsors/ljharb" 680 | } 681 | }, 682 | "node_modules/is-regex": { 683 | "version": "1.1.3", 684 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", 685 | "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", 686 | "dependencies": { 687 | "call-bind": "^1.0.2", 688 | "has-symbols": "^1.0.2" 689 | }, 690 | "engines": { 691 | "node": ">= 0.4" 692 | }, 693 | "funding": { 694 | "url": "https://github.com/sponsors/ljharb" 695 | } 696 | }, 697 | "node_modules/is-string": { 698 | "version": "1.0.6", 699 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", 700 | "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", 701 | "engines": { 702 | "node": ">= 0.4" 703 | }, 704 | "funding": { 705 | "url": "https://github.com/sponsors/ljharb" 706 | } 707 | }, 708 | "node_modules/is-symbol": { 709 | "version": "1.0.4", 710 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 711 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 712 | "dependencies": { 713 | "has-symbols": "^1.0.2" 714 | }, 715 | "engines": { 716 | "node": ">= 0.4" 717 | }, 718 | "funding": { 719 | "url": "https://github.com/sponsors/ljharb" 720 | } 721 | }, 722 | "node_modules/isarray": { 723 | "version": "1.0.0", 724 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 725 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 726 | }, 727 | "node_modules/jmespath": { 728 | "version": "0.15.0", 729 | "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", 730 | "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", 731 | "engines": { 732 | "node": ">= 0.6.0" 733 | } 734 | }, 735 | "node_modules/js-yaml": { 736 | "version": "3.14.1", 737 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 738 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 739 | "dependencies": { 740 | "argparse": "^1.0.7", 741 | "esprima": "^4.0.0" 742 | }, 743 | "bin": { 744 | "js-yaml": "bin/js-yaml.js" 745 | } 746 | }, 747 | "node_modules/json-parse-even-better-errors": { 748 | "version": "2.3.1", 749 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 750 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" 751 | }, 752 | "node_modules/long": { 753 | "version": "4.0.0", 754 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 755 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 756 | }, 757 | "node_modules/make-error": { 758 | "version": "1.3.6", 759 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 760 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" 761 | }, 762 | "node_modules/mime": { 763 | "version": "2.5.2", 764 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", 765 | "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", 766 | "bin": { 767 | "mime": "cli.js" 768 | }, 769 | "engines": { 770 | "node": ">=4.0.0" 771 | } 772 | }, 773 | "node_modules/mime-db": { 774 | "version": "1.48.0", 775 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", 776 | "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", 777 | "engines": { 778 | "node": ">= 0.6" 779 | } 780 | }, 781 | "node_modules/mime-types": { 782 | "version": "2.1.31", 783 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", 784 | "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", 785 | "dependencies": { 786 | "mime-db": "1.48.0" 787 | }, 788 | "engines": { 789 | "node": ">= 0.6" 790 | } 791 | }, 792 | "node_modules/minimatch": { 793 | "version": "3.0.4", 794 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 795 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 796 | "dependencies": { 797 | "brace-expansion": "^1.1.7" 798 | }, 799 | "engines": { 800 | "node": "*" 801 | } 802 | }, 803 | "node_modules/minimist": { 804 | "version": "1.2.5", 805 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 806 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 807 | }, 808 | "node_modules/mkdirp": { 809 | "version": "0.5.5", 810 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 811 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 812 | "dependencies": { 813 | "minimist": "^1.2.5" 814 | }, 815 | "bin": { 816 | "mkdirp": "bin/cmd.js" 817 | } 818 | }, 819 | "node_modules/node-fetch": { 820 | "version": "2.6.1", 821 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 822 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", 823 | "engines": { 824 | "node": "4.x || >=6.0.0" 825 | } 826 | }, 827 | "node_modules/normalize-package-data": { 828 | "version": "2.5.0", 829 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 830 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 831 | "dependencies": { 832 | "hosted-git-info": "^2.1.4", 833 | "resolve": "^1.10.0", 834 | "semver": "2 || 3 || 4 || 5", 835 | "validate-npm-package-license": "^3.0.1" 836 | } 837 | }, 838 | "node_modules/npm-normalize-package-bin": { 839 | "version": "1.0.1", 840 | "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", 841 | "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" 842 | }, 843 | "node_modules/object-inspect": { 844 | "version": "1.10.3", 845 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", 846 | "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", 847 | "funding": { 848 | "url": "https://github.com/sponsors/ljharb" 849 | } 850 | }, 851 | "node_modules/object-keys": { 852 | "version": "1.1.1", 853 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 854 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 855 | "engines": { 856 | "node": ">= 0.4" 857 | } 858 | }, 859 | "node_modules/object.assign": { 860 | "version": "4.1.2", 861 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", 862 | "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", 863 | "dependencies": { 864 | "call-bind": "^1.0.0", 865 | "define-properties": "^1.1.3", 866 | "has-symbols": "^1.0.1", 867 | "object-keys": "^1.1.1" 868 | }, 869 | "engines": { 870 | "node": ">= 0.4" 871 | }, 872 | "funding": { 873 | "url": "https://github.com/sponsors/ljharb" 874 | } 875 | }, 876 | "node_modules/object.getownpropertydescriptors": { 877 | "version": "2.1.2", 878 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", 879 | "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", 880 | "dependencies": { 881 | "call-bind": "^1.0.2", 882 | "define-properties": "^1.1.3", 883 | "es-abstract": "^1.18.0-next.2" 884 | }, 885 | "engines": { 886 | "node": ">= 0.8" 887 | }, 888 | "funding": { 889 | "url": "https://github.com/sponsors/ljharb" 890 | } 891 | }, 892 | "node_modules/once": { 893 | "version": "1.4.0", 894 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 895 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 896 | "dependencies": { 897 | "wrappy": "1" 898 | } 899 | }, 900 | "node_modules/os-tmpdir": { 901 | "version": "1.0.2", 902 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 903 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 904 | "engines": { 905 | "node": ">=0.10.0" 906 | } 907 | }, 908 | "node_modules/path-is-absolute": { 909 | "version": "1.0.1", 910 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 911 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 912 | "engines": { 913 | "node": ">=0.10.0" 914 | } 915 | }, 916 | "node_modules/path-parse": { 917 | "version": "1.0.7", 918 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 919 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 920 | }, 921 | "node_modules/protobufjs": { 922 | "version": "6.11.2", 923 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", 924 | "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", 925 | "hasInstallScript": true, 926 | "dependencies": { 927 | "@protobufjs/aspromise": "^1.1.2", 928 | "@protobufjs/base64": "^1.1.2", 929 | "@protobufjs/codegen": "^2.0.4", 930 | "@protobufjs/eventemitter": "^1.1.0", 931 | "@protobufjs/fetch": "^1.1.0", 932 | "@protobufjs/float": "^1.0.2", 933 | "@protobufjs/inquire": "^1.1.0", 934 | "@protobufjs/path": "^1.1.2", 935 | "@protobufjs/pool": "^1.1.0", 936 | "@protobufjs/utf8": "^1.1.0", 937 | "@types/long": "^4.0.1", 938 | "@types/node": ">=13.7.0", 939 | "long": "^4.0.0" 940 | }, 941 | "bin": { 942 | "pbjs": "bin/pbjs", 943 | "pbts": "bin/pbts" 944 | } 945 | }, 946 | "node_modules/protobufjs/node_modules/@types/node": { 947 | "version": "15.12.0", 948 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz", 949 | "integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==" 950 | }, 951 | "node_modules/punycode": { 952 | "version": "1.3.2", 953 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 954 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 955 | }, 956 | "node_modules/querystring": { 957 | "version": "0.2.0", 958 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 959 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", 960 | "engines": { 961 | "node": ">=0.4.x" 962 | } 963 | }, 964 | "node_modules/read-package-json": { 965 | "version": "2.1.2", 966 | "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz", 967 | "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==", 968 | "dependencies": { 969 | "glob": "^7.1.1", 970 | "json-parse-even-better-errors": "^2.3.0", 971 | "normalize-package-data": "^2.0.0", 972 | "npm-normalize-package-bin": "^1.0.0" 973 | } 974 | }, 975 | "node_modules/read-package-tree": { 976 | "version": "5.3.1", 977 | "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", 978 | "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", 979 | "dependencies": { 980 | "read-package-json": "^2.0.0", 981 | "readdir-scoped-modules": "^1.0.0", 982 | "util-promisify": "^2.1.0" 983 | } 984 | }, 985 | "node_modules/readdir-scoped-modules": { 986 | "version": "1.1.0", 987 | "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", 988 | "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", 989 | "dependencies": { 990 | "debuglog": "^1.0.1", 991 | "dezalgo": "^1.0.0", 992 | "graceful-fs": "^4.1.2", 993 | "once": "^1.3.0" 994 | } 995 | }, 996 | "node_modules/require-from-string": { 997 | "version": "2.0.2", 998 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 999 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 1000 | "engines": { 1001 | "node": ">=0.10.0" 1002 | } 1003 | }, 1004 | "node_modules/resolve": { 1005 | "version": "1.20.0", 1006 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 1007 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 1008 | "dependencies": { 1009 | "is-core-module": "^2.2.0", 1010 | "path-parse": "^1.0.6" 1011 | }, 1012 | "funding": { 1013 | "url": "https://github.com/sponsors/ljharb" 1014 | } 1015 | }, 1016 | "node_modules/sax": { 1017 | "version": "1.2.1", 1018 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", 1019 | "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" 1020 | }, 1021 | "node_modules/semver": { 1022 | "version": "5.7.1", 1023 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1024 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1025 | "bin": { 1026 | "semver": "bin/semver" 1027 | } 1028 | }, 1029 | "node_modules/shell-quote": { 1030 | "version": "1.7.2", 1031 | "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", 1032 | "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" 1033 | }, 1034 | "node_modules/source-map": { 1035 | "version": "0.5.7", 1036 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1037 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1038 | "engines": { 1039 | "node": ">=0.10.0" 1040 | } 1041 | }, 1042 | "node_modules/source-map-support": { 1043 | "version": "0.4.18", 1044 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", 1045 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", 1046 | "dependencies": { 1047 | "source-map": "^0.5.6" 1048 | } 1049 | }, 1050 | "node_modules/spdx-correct": { 1051 | "version": "3.1.1", 1052 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", 1053 | "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", 1054 | "dependencies": { 1055 | "spdx-expression-parse": "^3.0.0", 1056 | "spdx-license-ids": "^3.0.0" 1057 | } 1058 | }, 1059 | "node_modules/spdx-exceptions": { 1060 | "version": "2.3.0", 1061 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", 1062 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" 1063 | }, 1064 | "node_modules/spdx-expression-parse": { 1065 | "version": "3.0.1", 1066 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", 1067 | "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", 1068 | "dependencies": { 1069 | "spdx-exceptions": "^2.1.0", 1070 | "spdx-license-ids": "^3.0.0" 1071 | } 1072 | }, 1073 | "node_modules/spdx-license-ids": { 1074 | "version": "3.0.9", 1075 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", 1076 | "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==" 1077 | }, 1078 | "node_modules/sprintf-js": { 1079 | "version": "1.0.3", 1080 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1081 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 1082 | }, 1083 | "node_modules/string.prototype.trimend": { 1084 | "version": "1.0.4", 1085 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", 1086 | "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", 1087 | "dependencies": { 1088 | "call-bind": "^1.0.2", 1089 | "define-properties": "^1.1.3" 1090 | }, 1091 | "funding": { 1092 | "url": "https://github.com/sponsors/ljharb" 1093 | } 1094 | }, 1095 | "node_modules/string.prototype.trimstart": { 1096 | "version": "1.0.4", 1097 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", 1098 | "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", 1099 | "dependencies": { 1100 | "call-bind": "^1.0.2", 1101 | "define-properties": "^1.1.3" 1102 | }, 1103 | "funding": { 1104 | "url": "https://github.com/sponsors/ljharb" 1105 | } 1106 | }, 1107 | "node_modules/tmp": { 1108 | "version": "0.0.33", 1109 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1110 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1111 | "dependencies": { 1112 | "os-tmpdir": "~1.0.2" 1113 | }, 1114 | "engines": { 1115 | "node": ">=0.6.0" 1116 | } 1117 | }, 1118 | "node_modules/ts-node": { 1119 | "version": "7.0.1", 1120 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", 1121 | "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", 1122 | "dependencies": { 1123 | "arrify": "^1.0.0", 1124 | "buffer-from": "^1.1.0", 1125 | "diff": "^3.1.0", 1126 | "make-error": "^1.1.1", 1127 | "minimist": "^1.2.0", 1128 | "mkdirp": "^0.5.1", 1129 | "source-map-support": "^0.5.6", 1130 | "yn": "^2.0.0" 1131 | }, 1132 | "bin": { 1133 | "ts-node": "dist/bin.js" 1134 | }, 1135 | "engines": { 1136 | "node": ">=4.2.0" 1137 | } 1138 | }, 1139 | "node_modules/ts-node/node_modules/source-map": { 1140 | "version": "0.6.1", 1141 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1142 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1143 | "engines": { 1144 | "node": ">=0.10.0" 1145 | } 1146 | }, 1147 | "node_modules/ts-node/node_modules/source-map-support": { 1148 | "version": "0.5.19", 1149 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 1150 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 1151 | "dependencies": { 1152 | "buffer-from": "^1.0.0", 1153 | "source-map": "^0.6.0" 1154 | } 1155 | }, 1156 | "node_modules/typescript": { 1157 | "version": "3.7.7", 1158 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.7.tgz", 1159 | "integrity": "sha512-MmQdgo/XenfZPvVLtKZOq9jQQvzaUAUpcKW8Z43x9B2fOm4S5g//tPtMweZUIP+SoBqrVPEIm+dJeQ9dfO0QdA==", 1160 | "bin": { 1161 | "tsc": "bin/tsc", 1162 | "tsserver": "bin/tsserver" 1163 | }, 1164 | "engines": { 1165 | "node": ">=4.2.0" 1166 | } 1167 | }, 1168 | "node_modules/unbox-primitive": { 1169 | "version": "1.0.1", 1170 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", 1171 | "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", 1172 | "dependencies": { 1173 | "function-bind": "^1.1.1", 1174 | "has-bigints": "^1.0.1", 1175 | "has-symbols": "^1.0.2", 1176 | "which-boxed-primitive": "^1.0.2" 1177 | }, 1178 | "funding": { 1179 | "url": "https://github.com/sponsors/ljharb" 1180 | } 1181 | }, 1182 | "node_modules/upath": { 1183 | "version": "1.2.0", 1184 | "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", 1185 | "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", 1186 | "engines": { 1187 | "node": ">=4", 1188 | "yarn": "*" 1189 | } 1190 | }, 1191 | "node_modules/url": { 1192 | "version": "0.10.3", 1193 | "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", 1194 | "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", 1195 | "dependencies": { 1196 | "punycode": "1.3.2", 1197 | "querystring": "0.2.0" 1198 | } 1199 | }, 1200 | "node_modules/util-promisify": { 1201 | "version": "2.1.0", 1202 | "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", 1203 | "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", 1204 | "dependencies": { 1205 | "object.getownpropertydescriptors": "^2.0.3" 1206 | } 1207 | }, 1208 | "node_modules/uuid": { 1209 | "version": "3.3.2", 1210 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 1211 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", 1212 | "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", 1213 | "bin": { 1214 | "uuid": "bin/uuid" 1215 | } 1216 | }, 1217 | "node_modules/validate-npm-package-license": { 1218 | "version": "3.0.4", 1219 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 1220 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 1221 | "dependencies": { 1222 | "spdx-correct": "^3.0.0", 1223 | "spdx-expression-parse": "^3.0.0" 1224 | } 1225 | }, 1226 | "node_modules/which-boxed-primitive": { 1227 | "version": "1.0.2", 1228 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 1229 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 1230 | "dependencies": { 1231 | "is-bigint": "^1.0.1", 1232 | "is-boolean-object": "^1.1.0", 1233 | "is-number-object": "^1.0.4", 1234 | "is-string": "^1.0.5", 1235 | "is-symbol": "^1.0.3" 1236 | }, 1237 | "funding": { 1238 | "url": "https://github.com/sponsors/ljharb" 1239 | } 1240 | }, 1241 | "node_modules/wrappy": { 1242 | "version": "1.0.2", 1243 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1244 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1245 | }, 1246 | "node_modules/xml2js": { 1247 | "version": "0.4.19", 1248 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", 1249 | "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", 1250 | "dependencies": { 1251 | "sax": ">=0.6.0", 1252 | "xmlbuilder": "~9.0.1" 1253 | } 1254 | }, 1255 | "node_modules/xmlbuilder": { 1256 | "version": "9.0.7", 1257 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 1258 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", 1259 | "engines": { 1260 | "node": ">=4.0" 1261 | } 1262 | }, 1263 | "node_modules/yn": { 1264 | "version": "2.0.0", 1265 | "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", 1266 | "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", 1267 | "engines": { 1268 | "node": ">=4" 1269 | } 1270 | } 1271 | }, 1272 | "dependencies": { 1273 | "@grpc/grpc-js": { 1274 | "version": "1.3.2", 1275 | "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.3.2.tgz", 1276 | "integrity": "sha512-UXepkOKCATJrhHGsxt+CGfpZy9zUn1q9mop5kfcXq1fBkTePxVNPOdnISlCbJFlCtld+pSLGyZCzr9/zVprFKA==", 1277 | "requires": { 1278 | "@types/node": ">=12.12.47" 1279 | }, 1280 | "dependencies": { 1281 | "@types/node": { 1282 | "version": "15.12.0", 1283 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz", 1284 | "integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==" 1285 | } 1286 | } 1287 | }, 1288 | "@logdna/tail-file": { 1289 | "version": "2.0.7", 1290 | "resolved": "https://registry.npmjs.org/@logdna/tail-file/-/tail-file-2.0.7.tgz", 1291 | "integrity": "sha512-ycw0OrbphtfGOnygF+J4J/kJELXifLUiQ/CSTMb9Ztqjnuq4h+Id3MEvt4FTyyyekYbzStx7TjkhqXFW6Mi9LA==" 1292 | }, 1293 | "@protobufjs/aspromise": { 1294 | "version": "1.1.2", 1295 | "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", 1296 | "integrity": "sha1-m4sMxmPWaafY9vXQiToU00jzD78=" 1297 | }, 1298 | "@protobufjs/base64": { 1299 | "version": "1.1.2", 1300 | "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", 1301 | "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" 1302 | }, 1303 | "@protobufjs/codegen": { 1304 | "version": "2.0.4", 1305 | "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", 1306 | "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" 1307 | }, 1308 | "@protobufjs/eventemitter": { 1309 | "version": "1.1.0", 1310 | "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", 1311 | "integrity": "sha1-NVy8mLr61ZePntCV85diHx0Ga3A=" 1312 | }, 1313 | "@protobufjs/fetch": { 1314 | "version": "1.1.0", 1315 | "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", 1316 | "integrity": "sha1-upn7WYYUr2VwDBYZ/wbUVLDYTEU=", 1317 | "requires": { 1318 | "@protobufjs/aspromise": "^1.1.1", 1319 | "@protobufjs/inquire": "^1.1.0" 1320 | } 1321 | }, 1322 | "@protobufjs/float": { 1323 | "version": "1.0.2", 1324 | "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", 1325 | "integrity": "sha1-Xp4avctz/Ap8uLKR33jIy9l7h9E=" 1326 | }, 1327 | "@protobufjs/inquire": { 1328 | "version": "1.1.0", 1329 | "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", 1330 | "integrity": "sha1-/yAOPnzyQp4tyvwRQIKOjMY48Ik=" 1331 | }, 1332 | "@protobufjs/path": { 1333 | "version": "1.1.2", 1334 | "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", 1335 | "integrity": "sha1-bMKyDFya1q0NzP0hynZz2Nf79o0=" 1336 | }, 1337 | "@protobufjs/pool": { 1338 | "version": "1.1.0", 1339 | "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", 1340 | "integrity": "sha1-Cf0V8tbTq/qbZbw2ZQbWrXhG/1Q=" 1341 | }, 1342 | "@protobufjs/utf8": { 1343 | "version": "1.1.0", 1344 | "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", 1345 | "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" 1346 | }, 1347 | "@pulumi/aws": { 1348 | "version": "4.6.0", 1349 | "resolved": "https://registry.npmjs.org/@pulumi/aws/-/aws-4.6.0.tgz", 1350 | "integrity": "sha512-it0Q9FUd7v/2PgAvoXxTrTT/kQM1iwLNrxnBDabByQsGIOpp4jj4C+sexOoMH4IbKz6mwkLUaPS84QU/qDfndg==", 1351 | "requires": { 1352 | "@pulumi/pulumi": "^3.0.0", 1353 | "aws-sdk": "^2.0.0", 1354 | "builtin-modules": "3.0.0", 1355 | "mime": "^2.0.0", 1356 | "read-package-tree": "^5.2.1", 1357 | "resolve": "^1.7.1" 1358 | } 1359 | }, 1360 | "@pulumi/awsx": { 1361 | "version": "0.30.0", 1362 | "resolved": "https://registry.npmjs.org/@pulumi/awsx/-/awsx-0.30.0.tgz", 1363 | "integrity": "sha512-QtYVDFSkZxJ/JkAxaSwms9i/tJU2rA9F/VncCN6e8D0r29C5t4eYQhmB4chsLww9AjWJPRM7CXosDJs8+gy1Zg==", 1364 | "requires": { 1365 | "@pulumi/docker": "^3.0.0", 1366 | "@types/aws-lambda": "^8.10.23", 1367 | "mime": "^2.0.0" 1368 | } 1369 | }, 1370 | "@pulumi/docker": { 1371 | "version": "3.0.0", 1372 | "resolved": "https://registry.npmjs.org/@pulumi/docker/-/docker-3.0.0.tgz", 1373 | "integrity": "sha512-AzPhb/ibuHBy+GGDHrY3rPJeaO5DIMqv/ABtenQdoAw8X00E3UTV+D9dDS/GRq0oJ2aDvZupIlSdrPD7eJ5jgA==", 1374 | "requires": { 1375 | "@pulumi/pulumi": "^3.0.0", 1376 | "semver": "^5.4.0" 1377 | } 1378 | }, 1379 | "@pulumi/kubernetes": { 1380 | "version": "3.3.0", 1381 | "resolved": "https://registry.npmjs.org/@pulumi/kubernetes/-/kubernetes-3.3.0.tgz", 1382 | "integrity": "sha512-iM5qYPs6iaa7Wti/cX17mNMMpVCMWo5aaF7RKydiy+FYFY+SJ1sk0wBoVj/A0RxteIVEYU+NiFrfUMGKe4HjQw==", 1383 | "requires": { 1384 | "@pulumi/pulumi": "^3.0.0", 1385 | "@types/glob": "^5.0.35", 1386 | "@types/node-fetch": "^2.1.4", 1387 | "@types/tmp": "^0.0.33", 1388 | "glob": "^7.1.2", 1389 | "node-fetch": "^2.3.0", 1390 | "shell-quote": "^1.6.1", 1391 | "tmp": "^0.0.33" 1392 | } 1393 | }, 1394 | "@pulumi/kubernetesx": { 1395 | "version": "0.1.6", 1396 | "resolved": "https://registry.npmjs.org/@pulumi/kubernetesx/-/kubernetesx-0.1.6.tgz", 1397 | "integrity": "sha512-9VL4Yi4b4aLC/obBarJuNkm86kABByUZICYPSTdV396MGZtOc066o2brsB+kWVQcVfkYVXTPrpjIkAwBXXnzGw==", 1398 | "requires": {} 1399 | }, 1400 | "@pulumi/pulumi": { 1401 | "version": "3.3.1", 1402 | "resolved": "https://registry.npmjs.org/@pulumi/pulumi/-/pulumi-3.3.1.tgz", 1403 | "integrity": "sha512-W5HBFCQUY67QaPXtDSZ6Fe/K8mB+X7tJqi2pBU6UUUMtJVndcZ5BpLkZBznu+Nq/ZmitmGVaOpUqC5yK70D98A==", 1404 | "requires": { 1405 | "@grpc/grpc-js": "^1.2.7", 1406 | "@logdna/tail-file": "^2.0.6", 1407 | "@pulumi/query": "^0.3.0", 1408 | "google-protobuf": "^3.5.0", 1409 | "js-yaml": "^3.14.0", 1410 | "minimist": "^1.2.0", 1411 | "normalize-package-data": "^2.4.0", 1412 | "protobufjs": "^6.8.6", 1413 | "read-package-tree": "^5.3.1", 1414 | "require-from-string": "^2.0.1", 1415 | "semver": "^6.1.0", 1416 | "source-map-support": "^0.4.16", 1417 | "ts-node": "^7.0.1", 1418 | "typescript": "~3.7.3", 1419 | "upath": "^1.1.0" 1420 | }, 1421 | "dependencies": { 1422 | "semver": { 1423 | "version": "6.3.0", 1424 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1425 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" 1426 | } 1427 | } 1428 | }, 1429 | "@pulumi/query": { 1430 | "version": "0.3.0", 1431 | "resolved": "https://registry.npmjs.org/@pulumi/query/-/query-0.3.0.tgz", 1432 | "integrity": "sha512-xfo+yLRM2zVjVEA4p23IjQWzyWl1ZhWOGobsBqRpIarzLvwNH/RAGaoehdxlhx4X92302DrpdIFgTICMN4P38w==" 1433 | }, 1434 | "@types/aws-lambda": { 1435 | "version": "8.10.76", 1436 | "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.76.tgz", 1437 | "integrity": "sha512-lCTyeRm3NWqSwDnoji0z82Pl0tsOpr1p+33AiNeidgarloWXh3wdiVRUuxEa+sY9S5YLOYGz5X3N3Zvpibvm5w==" 1438 | }, 1439 | "@types/events": { 1440 | "version": "3.0.0", 1441 | "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", 1442 | "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" 1443 | }, 1444 | "@types/glob": { 1445 | "version": "5.0.36", 1446 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-5.0.36.tgz", 1447 | "integrity": "sha512-KEzSKuP2+3oOjYYjujue6Z3Yqis5HKA1BsIC+jZ1v3lrRNdsqyNNtX0rQf6LSuI4DJJ2z5UV//zBZCcvM0xikg==", 1448 | "requires": { 1449 | "@types/events": "*", 1450 | "@types/minimatch": "*", 1451 | "@types/node": "*" 1452 | } 1453 | }, 1454 | "@types/long": { 1455 | "version": "4.0.1", 1456 | "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", 1457 | "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" 1458 | }, 1459 | "@types/minimatch": { 1460 | "version": "3.0.4", 1461 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", 1462 | "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==" 1463 | }, 1464 | "@types/node": { 1465 | "version": "10.17.60", 1466 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", 1467 | "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==" 1468 | }, 1469 | "@types/node-fetch": { 1470 | "version": "2.5.10", 1471 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz", 1472 | "integrity": "sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==", 1473 | "requires": { 1474 | "@types/node": "*", 1475 | "form-data": "^3.0.0" 1476 | } 1477 | }, 1478 | "@types/tmp": { 1479 | "version": "0.0.33", 1480 | "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz", 1481 | "integrity": "sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=" 1482 | }, 1483 | "argparse": { 1484 | "version": "1.0.10", 1485 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 1486 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 1487 | "requires": { 1488 | "sprintf-js": "~1.0.2" 1489 | } 1490 | }, 1491 | "arrify": { 1492 | "version": "1.0.1", 1493 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 1494 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" 1495 | }, 1496 | "asap": { 1497 | "version": "2.0.6", 1498 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 1499 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 1500 | }, 1501 | "asynckit": { 1502 | "version": "0.4.0", 1503 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 1504 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 1505 | }, 1506 | "aws-sdk": { 1507 | "version": "2.920.0", 1508 | "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.920.0.tgz", 1509 | "integrity": "sha512-tbMZ/Y2rRo6R6TTBODJXTiil+MXaoT6Qzotws3yvI1IWGpYxKo7N/3L06XB8ul8tCG0TigxIOY70SMICM70Ppg==", 1510 | "requires": { 1511 | "buffer": "4.9.2", 1512 | "events": "1.1.1", 1513 | "ieee754": "1.1.13", 1514 | "jmespath": "0.15.0", 1515 | "querystring": "0.2.0", 1516 | "sax": "1.2.1", 1517 | "url": "0.10.3", 1518 | "uuid": "3.3.2", 1519 | "xml2js": "0.4.19" 1520 | } 1521 | }, 1522 | "balanced-match": { 1523 | "version": "1.0.2", 1524 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1525 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 1526 | }, 1527 | "base64-js": { 1528 | "version": "1.5.1", 1529 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 1530 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 1531 | }, 1532 | "brace-expansion": { 1533 | "version": "1.1.11", 1534 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1535 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1536 | "requires": { 1537 | "balanced-match": "^1.0.0", 1538 | "concat-map": "0.0.1" 1539 | } 1540 | }, 1541 | "buffer": { 1542 | "version": "4.9.2", 1543 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", 1544 | "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", 1545 | "requires": { 1546 | "base64-js": "^1.0.2", 1547 | "ieee754": "^1.1.4", 1548 | "isarray": "^1.0.0" 1549 | } 1550 | }, 1551 | "buffer-from": { 1552 | "version": "1.1.1", 1553 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 1554 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 1555 | }, 1556 | "builtin-modules": { 1557 | "version": "3.0.0", 1558 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.0.0.tgz", 1559 | "integrity": "sha512-hMIeU4K2ilbXV6Uv93ZZ0Avg/M91RaKXucQ+4me2Do1txxBDyDZWCBa5bJSLqoNTRpXTLwEzIk1KmloenDDjhg==" 1560 | }, 1561 | "call-bind": { 1562 | "version": "1.0.2", 1563 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 1564 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 1565 | "requires": { 1566 | "function-bind": "^1.1.1", 1567 | "get-intrinsic": "^1.0.2" 1568 | } 1569 | }, 1570 | "combined-stream": { 1571 | "version": "1.0.8", 1572 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 1573 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 1574 | "requires": { 1575 | "delayed-stream": "~1.0.0" 1576 | } 1577 | }, 1578 | "concat-map": { 1579 | "version": "0.0.1", 1580 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1581 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 1582 | }, 1583 | "debuglog": { 1584 | "version": "1.0.1", 1585 | "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", 1586 | "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" 1587 | }, 1588 | "define-properties": { 1589 | "version": "1.1.3", 1590 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 1591 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 1592 | "requires": { 1593 | "object-keys": "^1.0.12" 1594 | } 1595 | }, 1596 | "delayed-stream": { 1597 | "version": "1.0.0", 1598 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1599 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 1600 | }, 1601 | "dezalgo": { 1602 | "version": "1.0.3", 1603 | "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", 1604 | "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", 1605 | "requires": { 1606 | "asap": "^2.0.0", 1607 | "wrappy": "1" 1608 | } 1609 | }, 1610 | "diff": { 1611 | "version": "3.5.0", 1612 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 1613 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" 1614 | }, 1615 | "es-abstract": { 1616 | "version": "1.18.3", 1617 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", 1618 | "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", 1619 | "requires": { 1620 | "call-bind": "^1.0.2", 1621 | "es-to-primitive": "^1.2.1", 1622 | "function-bind": "^1.1.1", 1623 | "get-intrinsic": "^1.1.1", 1624 | "has": "^1.0.3", 1625 | "has-symbols": "^1.0.2", 1626 | "is-callable": "^1.2.3", 1627 | "is-negative-zero": "^2.0.1", 1628 | "is-regex": "^1.1.3", 1629 | "is-string": "^1.0.6", 1630 | "object-inspect": "^1.10.3", 1631 | "object-keys": "^1.1.1", 1632 | "object.assign": "^4.1.2", 1633 | "string.prototype.trimend": "^1.0.4", 1634 | "string.prototype.trimstart": "^1.0.4", 1635 | "unbox-primitive": "^1.0.1" 1636 | } 1637 | }, 1638 | "es-to-primitive": { 1639 | "version": "1.2.1", 1640 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 1641 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 1642 | "requires": { 1643 | "is-callable": "^1.1.4", 1644 | "is-date-object": "^1.0.1", 1645 | "is-symbol": "^1.0.2" 1646 | } 1647 | }, 1648 | "esprima": { 1649 | "version": "4.0.1", 1650 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1651 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 1652 | }, 1653 | "events": { 1654 | "version": "1.1.1", 1655 | "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", 1656 | "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" 1657 | }, 1658 | "form-data": { 1659 | "version": "3.0.1", 1660 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", 1661 | "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", 1662 | "requires": { 1663 | "asynckit": "^0.4.0", 1664 | "combined-stream": "^1.0.8", 1665 | "mime-types": "^2.1.12" 1666 | } 1667 | }, 1668 | "fs.realpath": { 1669 | "version": "1.0.0", 1670 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1671 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 1672 | }, 1673 | "function-bind": { 1674 | "version": "1.1.1", 1675 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1676 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 1677 | }, 1678 | "get-intrinsic": { 1679 | "version": "1.1.1", 1680 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 1681 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 1682 | "requires": { 1683 | "function-bind": "^1.1.1", 1684 | "has": "^1.0.3", 1685 | "has-symbols": "^1.0.1" 1686 | } 1687 | }, 1688 | "glob": { 1689 | "version": "7.1.7", 1690 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 1691 | "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 1692 | "requires": { 1693 | "fs.realpath": "^1.0.0", 1694 | "inflight": "^1.0.4", 1695 | "inherits": "2", 1696 | "minimatch": "^3.0.4", 1697 | "once": "^1.3.0", 1698 | "path-is-absolute": "^1.0.0" 1699 | } 1700 | }, 1701 | "google-protobuf": { 1702 | "version": "3.17.2", 1703 | "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.17.2.tgz", 1704 | "integrity": "sha512-LlFVMhSkNy6C1MakEjiwbLxq5w+V+Go+mvt2EUoysrp8gXl903ic2W/3BwzM4/WnDMJP+u7UO2efUSl/0CJMzA==" 1705 | }, 1706 | "graceful-fs": { 1707 | "version": "4.2.6", 1708 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", 1709 | "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" 1710 | }, 1711 | "has": { 1712 | "version": "1.0.3", 1713 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1714 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1715 | "requires": { 1716 | "function-bind": "^1.1.1" 1717 | } 1718 | }, 1719 | "has-bigints": { 1720 | "version": "1.0.1", 1721 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", 1722 | "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" 1723 | }, 1724 | "has-symbols": { 1725 | "version": "1.0.2", 1726 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 1727 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" 1728 | }, 1729 | "hosted-git-info": { 1730 | "version": "2.8.9", 1731 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", 1732 | "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" 1733 | }, 1734 | "ieee754": { 1735 | "version": "1.1.13", 1736 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 1737 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 1738 | }, 1739 | "inflight": { 1740 | "version": "1.0.6", 1741 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1742 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1743 | "requires": { 1744 | "once": "^1.3.0", 1745 | "wrappy": "1" 1746 | } 1747 | }, 1748 | "inherits": { 1749 | "version": "2.0.4", 1750 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1751 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1752 | }, 1753 | "is-bigint": { 1754 | "version": "1.0.2", 1755 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", 1756 | "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==" 1757 | }, 1758 | "is-boolean-object": { 1759 | "version": "1.1.1", 1760 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", 1761 | "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", 1762 | "requires": { 1763 | "call-bind": "^1.0.2" 1764 | } 1765 | }, 1766 | "is-callable": { 1767 | "version": "1.2.3", 1768 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", 1769 | "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==" 1770 | }, 1771 | "is-core-module": { 1772 | "version": "2.4.0", 1773 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", 1774 | "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", 1775 | "requires": { 1776 | "has": "^1.0.3" 1777 | } 1778 | }, 1779 | "is-date-object": { 1780 | "version": "1.0.4", 1781 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", 1782 | "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==" 1783 | }, 1784 | "is-negative-zero": { 1785 | "version": "2.0.1", 1786 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", 1787 | "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" 1788 | }, 1789 | "is-number-object": { 1790 | "version": "1.0.5", 1791 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", 1792 | "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==" 1793 | }, 1794 | "is-regex": { 1795 | "version": "1.1.3", 1796 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", 1797 | "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", 1798 | "requires": { 1799 | "call-bind": "^1.0.2", 1800 | "has-symbols": "^1.0.2" 1801 | } 1802 | }, 1803 | "is-string": { 1804 | "version": "1.0.6", 1805 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", 1806 | "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==" 1807 | }, 1808 | "is-symbol": { 1809 | "version": "1.0.4", 1810 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 1811 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 1812 | "requires": { 1813 | "has-symbols": "^1.0.2" 1814 | } 1815 | }, 1816 | "isarray": { 1817 | "version": "1.0.0", 1818 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1819 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 1820 | }, 1821 | "jmespath": { 1822 | "version": "0.15.0", 1823 | "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", 1824 | "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" 1825 | }, 1826 | "js-yaml": { 1827 | "version": "3.14.1", 1828 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 1829 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 1830 | "requires": { 1831 | "argparse": "^1.0.7", 1832 | "esprima": "^4.0.0" 1833 | } 1834 | }, 1835 | "json-parse-even-better-errors": { 1836 | "version": "2.3.1", 1837 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 1838 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" 1839 | }, 1840 | "long": { 1841 | "version": "4.0.0", 1842 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 1843 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 1844 | }, 1845 | "make-error": { 1846 | "version": "1.3.6", 1847 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 1848 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" 1849 | }, 1850 | "mime": { 1851 | "version": "2.5.2", 1852 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", 1853 | "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" 1854 | }, 1855 | "mime-db": { 1856 | "version": "1.48.0", 1857 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", 1858 | "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" 1859 | }, 1860 | "mime-types": { 1861 | "version": "2.1.31", 1862 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", 1863 | "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", 1864 | "requires": { 1865 | "mime-db": "1.48.0" 1866 | } 1867 | }, 1868 | "minimatch": { 1869 | "version": "3.0.4", 1870 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1871 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1872 | "requires": { 1873 | "brace-expansion": "^1.1.7" 1874 | } 1875 | }, 1876 | "minimist": { 1877 | "version": "1.2.5", 1878 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1879 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 1880 | }, 1881 | "mkdirp": { 1882 | "version": "0.5.5", 1883 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 1884 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 1885 | "requires": { 1886 | "minimist": "^1.2.5" 1887 | } 1888 | }, 1889 | "node-fetch": { 1890 | "version": "2.6.1", 1891 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 1892 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" 1893 | }, 1894 | "normalize-package-data": { 1895 | "version": "2.5.0", 1896 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 1897 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 1898 | "requires": { 1899 | "hosted-git-info": "^2.1.4", 1900 | "resolve": "^1.10.0", 1901 | "semver": "2 || 3 || 4 || 5", 1902 | "validate-npm-package-license": "^3.0.1" 1903 | } 1904 | }, 1905 | "npm-normalize-package-bin": { 1906 | "version": "1.0.1", 1907 | "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", 1908 | "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" 1909 | }, 1910 | "object-inspect": { 1911 | "version": "1.10.3", 1912 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", 1913 | "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==" 1914 | }, 1915 | "object-keys": { 1916 | "version": "1.1.1", 1917 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1918 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" 1919 | }, 1920 | "object.assign": { 1921 | "version": "4.1.2", 1922 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", 1923 | "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", 1924 | "requires": { 1925 | "call-bind": "^1.0.0", 1926 | "define-properties": "^1.1.3", 1927 | "has-symbols": "^1.0.1", 1928 | "object-keys": "^1.1.1" 1929 | } 1930 | }, 1931 | "object.getownpropertydescriptors": { 1932 | "version": "2.1.2", 1933 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", 1934 | "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", 1935 | "requires": { 1936 | "call-bind": "^1.0.2", 1937 | "define-properties": "^1.1.3", 1938 | "es-abstract": "^1.18.0-next.2" 1939 | } 1940 | }, 1941 | "once": { 1942 | "version": "1.4.0", 1943 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1944 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1945 | "requires": { 1946 | "wrappy": "1" 1947 | } 1948 | }, 1949 | "os-tmpdir": { 1950 | "version": "1.0.2", 1951 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1952 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 1953 | }, 1954 | "path-is-absolute": { 1955 | "version": "1.0.1", 1956 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1957 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1958 | }, 1959 | "path-parse": { 1960 | "version": "1.0.7", 1961 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1962 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 1963 | }, 1964 | "protobufjs": { 1965 | "version": "6.11.2", 1966 | "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.2.tgz", 1967 | "integrity": "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw==", 1968 | "requires": { 1969 | "@protobufjs/aspromise": "^1.1.2", 1970 | "@protobufjs/base64": "^1.1.2", 1971 | "@protobufjs/codegen": "^2.0.4", 1972 | "@protobufjs/eventemitter": "^1.1.0", 1973 | "@protobufjs/fetch": "^1.1.0", 1974 | "@protobufjs/float": "^1.0.2", 1975 | "@protobufjs/inquire": "^1.1.0", 1976 | "@protobufjs/path": "^1.1.2", 1977 | "@protobufjs/pool": "^1.1.0", 1978 | "@protobufjs/utf8": "^1.1.0", 1979 | "@types/long": "^4.0.1", 1980 | "@types/node": ">=13.7.0", 1981 | "long": "^4.0.0" 1982 | }, 1983 | "dependencies": { 1984 | "@types/node": { 1985 | "version": "15.12.0", 1986 | "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.0.tgz", 1987 | "integrity": "sha512-+aHJvoCsVhO2ZCuT4o5JtcPrCPyDE3+1nvbDprYes+pPkEsbjH7AGUCNtjMOXS0fqH14t+B7yLzaqSz92FPWyw==" 1988 | } 1989 | } 1990 | }, 1991 | "punycode": { 1992 | "version": "1.3.2", 1993 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 1994 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 1995 | }, 1996 | "querystring": { 1997 | "version": "0.2.0", 1998 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1999 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 2000 | }, 2001 | "read-package-json": { 2002 | "version": "2.1.2", 2003 | "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz", 2004 | "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==", 2005 | "requires": { 2006 | "glob": "^7.1.1", 2007 | "json-parse-even-better-errors": "^2.3.0", 2008 | "normalize-package-data": "^2.0.0", 2009 | "npm-normalize-package-bin": "^1.0.0" 2010 | } 2011 | }, 2012 | "read-package-tree": { 2013 | "version": "5.3.1", 2014 | "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", 2015 | "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", 2016 | "requires": { 2017 | "read-package-json": "^2.0.0", 2018 | "readdir-scoped-modules": "^1.0.0", 2019 | "util-promisify": "^2.1.0" 2020 | } 2021 | }, 2022 | "readdir-scoped-modules": { 2023 | "version": "1.1.0", 2024 | "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", 2025 | "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", 2026 | "requires": { 2027 | "debuglog": "^1.0.1", 2028 | "dezalgo": "^1.0.0", 2029 | "graceful-fs": "^4.1.2", 2030 | "once": "^1.3.0" 2031 | } 2032 | }, 2033 | "require-from-string": { 2034 | "version": "2.0.2", 2035 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 2036 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" 2037 | }, 2038 | "resolve": { 2039 | "version": "1.20.0", 2040 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", 2041 | "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", 2042 | "requires": { 2043 | "is-core-module": "^2.2.0", 2044 | "path-parse": "^1.0.6" 2045 | } 2046 | }, 2047 | "sax": { 2048 | "version": "1.2.1", 2049 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", 2050 | "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" 2051 | }, 2052 | "semver": { 2053 | "version": "5.7.1", 2054 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 2055 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 2056 | }, 2057 | "shell-quote": { 2058 | "version": "1.7.2", 2059 | "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", 2060 | "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" 2061 | }, 2062 | "source-map": { 2063 | "version": "0.5.7", 2064 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 2065 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 2066 | }, 2067 | "source-map-support": { 2068 | "version": "0.4.18", 2069 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", 2070 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", 2071 | "requires": { 2072 | "source-map": "^0.5.6" 2073 | } 2074 | }, 2075 | "spdx-correct": { 2076 | "version": "3.1.1", 2077 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", 2078 | "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", 2079 | "requires": { 2080 | "spdx-expression-parse": "^3.0.0", 2081 | "spdx-license-ids": "^3.0.0" 2082 | } 2083 | }, 2084 | "spdx-exceptions": { 2085 | "version": "2.3.0", 2086 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", 2087 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" 2088 | }, 2089 | "spdx-expression-parse": { 2090 | "version": "3.0.1", 2091 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", 2092 | "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", 2093 | "requires": { 2094 | "spdx-exceptions": "^2.1.0", 2095 | "spdx-license-ids": "^3.0.0" 2096 | } 2097 | }, 2098 | "spdx-license-ids": { 2099 | "version": "3.0.9", 2100 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", 2101 | "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==" 2102 | }, 2103 | "sprintf-js": { 2104 | "version": "1.0.3", 2105 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2106 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" 2107 | }, 2108 | "string.prototype.trimend": { 2109 | "version": "1.0.4", 2110 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", 2111 | "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", 2112 | "requires": { 2113 | "call-bind": "^1.0.2", 2114 | "define-properties": "^1.1.3" 2115 | } 2116 | }, 2117 | "string.prototype.trimstart": { 2118 | "version": "1.0.4", 2119 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", 2120 | "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", 2121 | "requires": { 2122 | "call-bind": "^1.0.2", 2123 | "define-properties": "^1.1.3" 2124 | } 2125 | }, 2126 | "tmp": { 2127 | "version": "0.0.33", 2128 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 2129 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 2130 | "requires": { 2131 | "os-tmpdir": "~1.0.2" 2132 | } 2133 | }, 2134 | "ts-node": { 2135 | "version": "7.0.1", 2136 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", 2137 | "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", 2138 | "requires": { 2139 | "arrify": "^1.0.0", 2140 | "buffer-from": "^1.1.0", 2141 | "diff": "^3.1.0", 2142 | "make-error": "^1.1.1", 2143 | "minimist": "^1.2.0", 2144 | "mkdirp": "^0.5.1", 2145 | "source-map-support": "^0.5.6", 2146 | "yn": "^2.0.0" 2147 | }, 2148 | "dependencies": { 2149 | "source-map": { 2150 | "version": "0.6.1", 2151 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2152 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 2153 | }, 2154 | "source-map-support": { 2155 | "version": "0.5.19", 2156 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 2157 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 2158 | "requires": { 2159 | "buffer-from": "^1.0.0", 2160 | "source-map": "^0.6.0" 2161 | } 2162 | } 2163 | } 2164 | }, 2165 | "typescript": { 2166 | "version": "3.7.7", 2167 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.7.tgz", 2168 | "integrity": "sha512-MmQdgo/XenfZPvVLtKZOq9jQQvzaUAUpcKW8Z43x9B2fOm4S5g//tPtMweZUIP+SoBqrVPEIm+dJeQ9dfO0QdA==" 2169 | }, 2170 | "unbox-primitive": { 2171 | "version": "1.0.1", 2172 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", 2173 | "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", 2174 | "requires": { 2175 | "function-bind": "^1.1.1", 2176 | "has-bigints": "^1.0.1", 2177 | "has-symbols": "^1.0.2", 2178 | "which-boxed-primitive": "^1.0.2" 2179 | } 2180 | }, 2181 | "upath": { 2182 | "version": "1.2.0", 2183 | "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", 2184 | "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" 2185 | }, 2186 | "url": { 2187 | "version": "0.10.3", 2188 | "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", 2189 | "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", 2190 | "requires": { 2191 | "punycode": "1.3.2", 2192 | "querystring": "0.2.0" 2193 | } 2194 | }, 2195 | "util-promisify": { 2196 | "version": "2.1.0", 2197 | "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", 2198 | "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", 2199 | "requires": { 2200 | "object.getownpropertydescriptors": "^2.0.3" 2201 | } 2202 | }, 2203 | "uuid": { 2204 | "version": "3.3.2", 2205 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 2206 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 2207 | }, 2208 | "validate-npm-package-license": { 2209 | "version": "3.0.4", 2210 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 2211 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 2212 | "requires": { 2213 | "spdx-correct": "^3.0.0", 2214 | "spdx-expression-parse": "^3.0.0" 2215 | } 2216 | }, 2217 | "which-boxed-primitive": { 2218 | "version": "1.0.2", 2219 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 2220 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 2221 | "requires": { 2222 | "is-bigint": "^1.0.1", 2223 | "is-boolean-object": "^1.1.0", 2224 | "is-number-object": "^1.0.4", 2225 | "is-string": "^1.0.5", 2226 | "is-symbol": "^1.0.3" 2227 | } 2228 | }, 2229 | "wrappy": { 2230 | "version": "1.0.2", 2231 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2232 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 2233 | }, 2234 | "xml2js": { 2235 | "version": "0.4.19", 2236 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", 2237 | "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", 2238 | "requires": { 2239 | "sax": ">=0.6.0", 2240 | "xmlbuilder": "~9.0.1" 2241 | } 2242 | }, 2243 | "xmlbuilder": { 2244 | "version": "9.0.7", 2245 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 2246 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" 2247 | }, 2248 | "yn": { 2249 | "version": "2.0.0", 2250 | "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", 2251 | "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=" 2252 | } 2253 | } 2254 | } 2255 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/infra/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{cookiecutter.project_slug}}-infra", 3 | "devDependencies": { 4 | "@types/node": "^10.0.0" 5 | }, 6 | "dependencies": { 7 | "@pulumi/aws": "^4.0.0", 8 | "@pulumi/awsx": "^0.30.0", 9 | "@pulumi/kubernetes": "^3.3.0", 10 | "@pulumi/kubernetesx": "^0.1.6", 11 | "@pulumi/pulumi": "^3.0.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/infra/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "outDir": "bin", 5 | "target": "es2016", 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "sourceMap": true, 9 | "experimentalDecorators": true, 10 | "pretty": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "noImplicitReturns": true, 13 | "forceConsistentCasingInFileNames": true 14 | }, 15 | "files": [ 16 | "index.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "{{cookiecutter.project_slug}}" 3 | version = "{{ cookiecutter.version }}" 4 | description = "{{ cookiecutter.project_short_description }}" 5 | authors = ["{{ cookiecutter.full_name.replace("\"", "\\\"") }} <{{ cookiecutter.email }}>"] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.8" 9 | mlflow = "^1.17.0" 10 | lightgbm = "^3.2.1" 11 | matplotlib = "^3.4.2" 12 | scikit-learn = "^0.24.2" 13 | boto3 = "1.17.49" 14 | fastapi = "^0.65.1" 15 | uvicorn = "^0.14.0" 16 | dvc = {extras = ["s3"], version = "^2.3.0"} 17 | 18 | [tool.poetry.dev-dependencies] 19 | pytest = "^5.2" 20 | 21 | [tool.poetry.scripts] 22 | train = "src.{{cookiecutter.module_name}}.training.train:main" 23 | serve = "src.{{cookiecutter.module_name}}.serving.__main__:main" 24 | 25 | [build-system] 26 | requires = ["poetry>=0.12"] 27 | build-backend = "poetry.masonry.api" 28 | 29 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/src/{{cookiecutter.module_name}}/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '{{ cookiecutter.version }}' 2 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/src/{{cookiecutter.module_name}}/serving/EXAMPLES.md: -------------------------------------------------------------------------------- 1 | Should be Setosa: 2 | 3 | { 4 | "sepal": { "length": 4.9, "width": 3.1 }, 5 | "petal": { "length": 1.5, "width": 0.1 } 6 | } 7 | 8 | 9 | Should be Virginica: 10 | 11 | { 12 | "sepal": { "length": 6.8, "width": 3 }, 13 | "petal": { "length": 5.5, "width": 2.1 } 14 | } 15 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/src/{{cookiecutter.module_name}}/serving/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aporia-ai/mlplatform-workshop/268141ed1d2d6c3b18c743680945bda92265cef1/model-template/{{cookiecutter.project_slug}}/src/{{cookiecutter.module_name}}/serving/__init__.py -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/src/{{cookiecutter.module_name}}/serving/__main__.py: -------------------------------------------------------------------------------- 1 | import os 2 | import uvicorn 3 | import mlflow 4 | import numpy as np 5 | import pandas as pd 6 | from fastapi import FastAPI, Request 7 | from pydantic import BaseModel 8 | 9 | 10 | class Size(BaseModel): 11 | length: float 12 | width: float 13 | 14 | class PredictRequest(BaseModel): 15 | sepal: Size 16 | petal: Size 17 | 18 | 19 | app = FastAPI() 20 | 21 | model = mlflow.lightgbm.load_model(f'runs:/{os.environ["MLFLOW_RUN_ID"]}/model') 22 | flower_name_by_index = {0: 'Setosa', 1: 'Versicolor', 2: 'Virginica'} 23 | 24 | 25 | @app.post("/predict") 26 | def predict(request: PredictRequest): 27 | df = pd.DataFrame(columns=['sepal.length', 'sepal.width', 'petal.length', 'petal.width'], 28 | data=[[request.sepal.length, request.sepal.width, request.petal.length, request.petal.width]]) 29 | 30 | y_pred = np.argmax(model.predict(df)) 31 | return {"flower": flower_name_by_index[y_pred]} 32 | 33 | 34 | def main(): 35 | uvicorn.run(app, host="0.0.0.0", port=8000) 36 | 37 | if __name__ == "__main__": 38 | main() 39 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/src/{{cookiecutter.module_name}}/training/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aporia-ai/mlplatform-workshop/268141ed1d2d6c3b18c743680945bda92265cef1/model-template/{{cookiecutter.project_slug}}/src/{{cookiecutter.module_name}}/training/__init__.py -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/src/{{cookiecutter.module_name}}/training/train.py: -------------------------------------------------------------------------------- 1 | from sklearn.model_selection import train_test_split 2 | from sklearn.metrics import accuracy_score, log_loss 3 | import pandas as pd 4 | import lightgbm as lgb 5 | import mlflow 6 | import mlflow.lightgbm 7 | 8 | 9 | # Enable auto logging 10 | mlflow.set_tracking_uri('http://ml.mycompany.com/mlflow') 11 | mlflow.lightgbm.autolog() 12 | 13 | 14 | # Prepare training data 15 | df = pd.read_csv('data/iris.csv') 16 | flower_names = {'Setosa': 0, 'Versicolor': 1, 'Virginica': 2} 17 | 18 | 19 | X = df[['sepal.length', 'sepal.width', 'petal.length', 'petal.width']] 20 | y = df['variety'].map(flower_names) 21 | 22 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) 23 | 24 | train_data = lgb.Dataset(X_train, label=y_train) 25 | 26 | def main(): 27 | with mlflow.start_run() as run: 28 | # Train model 29 | params = { 30 | "objective": "multiclass", 31 | "num_class": 3, 32 | "learning_rate": 0.2, 33 | "metric": "multi_logloss", 34 | "feature_fraction": 0.8, 35 | "bagging_fraction": 0.9, 36 | "seed": 42, 37 | } 38 | 39 | model = lgb.train(params, train_data, valid_sets=[train_data]) 40 | 41 | # Evaluate model 42 | y_proba = model.predict(X_test) 43 | y_pred = y_proba.argmax(axis=1) 44 | 45 | loss = log_loss(y_test, y_proba) 46 | acc = accuracy_score(y_test, y_pred) 47 | 48 | # Log metrics 49 | mlflow.log_metrics({ 50 | "log_loss": loss, 51 | "accuracy": acc 52 | }) 53 | 54 | print("Run ID:", run.info.run_id) 55 | 56 | if __name__ == "__main__": 57 | main() 58 | -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aporia-ai/mlplatform-workshop/268141ed1d2d6c3b18c743680945bda92265cef1/model-template/{{cookiecutter.project_slug}}/tests/__init__.py -------------------------------------------------------------------------------- /model-template/{{cookiecutter.project_slug}}/tests/test_{{cookiecutter.module_name}}.py: -------------------------------------------------------------------------------- 1 | from {{cookiecutter.module_name}} import __version__ 2 | 3 | 4 | def test_version(): 5 | assert __version__ == '0.1.0' 6 | --------------------------------------------------------------------------------