From e7539836c8011ae3484d8e82ac5a43101e6c95e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roch=C3=A9=20Compaan?= <roche@upfrontsoftware.co.za> Date: Fri, 27 Dec 2024 08:49:29 +0200 Subject: [PATCH 1/6] feat: Add k3s as option for kubernetes install. close #167 --- cookiecutter.json | 15 +- .../bootstrap-cluster/.env | 7 + .../bootstrap-cluster/.gitignore | 4 + .../bootstrap-cluster/README.md | 114 +++++++-- .../bootstrap-cluster/k3s.yaml | 237 ++++++++++++++++++ .../bootstrap-cluster/taskfile.yaml | 4 + .../terraform/README.md | 94 +++---- .../terraform/modules/base/ec2.tf | 34 ++- .../terraform/modules/base/outputs.tf | 16 +- .../terraform/modules/base/security_groups.tf | 15 +- .../terraform/modules/base/variables.tf | 12 +- .../terraform/modules/base/versions.tf | 12 - .../terraform/prod/cluster.tf | 5 +- .../terraform/sandbox/cluster.tf | 5 +- .../terraform/staging/cluster.tf | 5 +- 15 files changed, 466 insertions(+), 113 deletions(-) create mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/.env create mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/k3s.yaml diff --git a/cookiecutter.json b/cookiecutter.json index 1c2b4b35..9f9bfb6d 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -11,20 +11,13 @@ "aws_region": "us-east-1", "aws_account_id": "000000000000", "create_nextjs_frontend": "y", - "mail_service": [ - "Mailgun", - "Amazon SES", - "Other SMTP" - ], + "debug": "n", + "mail_service": ["Mailgun", "Amazon SES", "Other SMTP"], + "operating_system": ["k3s", "talos"], "_challenge": "n", "use_celery": "n", "use_sentry": "n", - "debug": "n", - "source_control_provider": [ - "github.com", - "bitbucket.org", - "none" - ], + "source_control_provider": ["github.com", "bitbucket.org", "none"], "source_control_organization_slug": "sixfeetup", "__prompts__": { "source_control_organization_slug": "What is the organization slug for the source control provider?", diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/.env b/{{cookiecutter.project_slug}}/bootstrap-cluster/.env new file mode 100644 index 00000000..ec2a3f5e --- /dev/null +++ b/{{cookiecutter.project_slug}}/bootstrap-cluster/.env @@ -0,0 +1,7 @@ +TOFU_DIR: "../terraform" +{%- if cookiecutter.operating_system == "talos" %} +TALOS_FACTORY_IMAGE: "factory.talos.dev/installer/10e276a06c1f86b182757a962258ac00655d3425e5957f617bdc82f06894e39b:v1.7.6" +{%- endif %} +ARGOCD_VERSION: 7.4.1 +REPO_URL: "{{ cookiecutter.repo_url }}" +REPO_NAME: "{{ cookiecutter.repo_name }}" diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/.gitignore b/{{cookiecutter.project_slug}}/bootstrap-cluster/.gitignore index 322b2ade..fe7a98fb 100644 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/.gitignore +++ b/{{cookiecutter.project_slug}}/bootstrap-cluster/.gitignore @@ -1,7 +1,11 @@ !sandbox/.env !staging/.env !prod/.env +!.env controlplane.yaml kubeconfig talosconfig worker.yaml +id_ed25519 +*_ips.txt +*.bak.* diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/README.md b/{{cookiecutter.project_slug}}/bootstrap-cluster/README.md index 01d3595a..084d143c 100644 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/README.md +++ b/{{cookiecutter.project_slug}}/bootstrap-cluster/README.md @@ -1,10 +1,18 @@ -# Bootstrap Talos and ArgoCD +{%- if cookiecutter.operating_system == "talos" %}# Bootstrap Talos and ArgoCD After deploying infrastructure using Terraform, we can proceed with configuring Talos and bootstrapping ArgoCD. Terraform is solely utilized for deploying infrastructure. Any subsequent configuration of Talos or ArgoCD is done using Taskfile tasks. +{%- elif cookiecutter.operating_system == "k3s" %}# Bootstrap k3s and ArgoCD + +After deploying infrastructure using Terraform, we can proceed with configuring +k3s and bootstrapping ArgoCD. + +Terraform is solely utilized for deploying infrastructure. Any subsequent +configuration of k3s or ArgoCD is done using Taskfile tasks. +{%- endif %} To view a list of tasks and their descriptions, navigate to the `bootstrap-cluster` directory and execute `task`. @@ -15,8 +23,16 @@ cluster. We recommend opening the AWS serial console for each ec2 instance to monitor the bootstrap process. +{%- if cookiecutter.operating_system == "talos" %} + ### Bootstrapping Talos +{%- elif cookiecutter.operating_system == "k3s" %} + +### Bootstrapping k3s + +{%- endif %} + 1. Navigate to the directory corresponding to the environment being set up and run: @@ -32,6 +48,7 @@ bootstrap process. CLUSTER_NAME: "{{ cookiecutter.project_dash }}-sandbox" ``` +{%- if cookiecutter.operating_system == "talos" %} Note that we use a Talos factory image. This image contains a system extension that provides the ECR credential provider. @@ -42,7 +59,8 @@ bootstrap process. CredentialProvider API to authenticate against AWS' Elastic Container Registry and pull images. ``` - +{%- endif %} +{%- if cookiecutter.operating_system == "talos" %} 3. Bootstrap Talos with the following command: ``` @@ -51,45 +69,84 @@ bootstrap process. To understand what this task will do, examine the Taskfile configuration: + ```yaml + bootstrap: + desc: | + Run all tasks required to bootstrap the Talos and Kubernetes cluster. + requires: + vars: [ENV] + cmds: + - task: generate_configs + - task: set_node_ips + - task: store_controlplane_config + - task: store_talosconfig + - task: apply_talos_config + - sleep 30 + - task: bootstrap_kubernetes + - sleep 30 + - task: generate_kubeconfig + - task: store_kubeconfig + - task: upgrade_talos + - task: enable_ecr_credential_helper ``` + + It takes a few minutes for the cluster nodes to register as etcd + members and synchronize. + +{%- elif cookiecutter.operating_system == "k3s" %} +3. Bootstrap k3s with the following command: + + ``` + task k3s:bootstrap + ``` + + To understand what this task will do, examine the Taskfile configuration: + + ```yaml bootstrap: - desc: | - Run all tasks required to bootstrap the Talos and Kubernetes cluster. - requires: - vars: [ENV] - cmds: - - task: generate_configs - - task: set_node_ips - - task: store_controlplane_config - - task: store_talosconfig - - task: apply_talos_config - - sleep 30 - - task: bootstrap_kubernetes - - sleep 30 - - task: generate_kubeconfig - - task: store_kubeconfig - - task: upgrade_talos - - task: enable_ecr_credential_helper + desc: | + Run all tasks required to bootstrap k3s and Kubernetes cluster. + requires: + vars: [ENV] + cmds: + - task: save-node-ips + - task: setup-ssh-key + - task: install-k3s + - task: fetch-kubeconfig + - task: store-kubeconfig + - task: enable-ecr-credential-helper ``` It takes a few minutes for the cluster nodes to register as etcd members and synchronize. +{%- endif %} + If the cluster fails to bootstrap, refer to the Troubleshooting section below. +{%- if cookiecutter.operating_system == "talos" %} 4. Verify the health of your cluster with: - ```shell - task talos:health - ``` + ```shell + task talos:health + ``` + + 5. Test kubectl access: -5. Test kubectl access: + ```shell + eval $(task talos:kubeconfig) + kubectl cluster-info + ``` +{%- elif cookiecutter.operating_system == "k3s" %} + +4. Test kubectl access: ```shell - eval $(task talos:kubeconfig) + eval $(task k3s:kubeconfig) kubectl cluster-info ``` +{%- endif %} This should return output similar to the following: @@ -205,6 +262,7 @@ The `argocd:bootstrap` task configuration is as follows: ## Troubleshooting +{%- if cookiecutter.operating_system == "talos" %} If bootstrapping Talos fails, we recommend resetting the config files and recreating ec2 instances before trying again. @@ -220,3 +278,11 @@ recreating ec2 instances before trying again. -target "module.c luster.module.control_plane_nodes[1].aws_instance.this[0]" terraform plan -out="tfplan.out" terraform apply tfplan.out +{%- elif cookiecutter.operating_system == "k3s" %} +If bootstrapping k3s fails, we recommend uninstalling k3s from each node and +boostrapping from scratch. + +```shell +task k3s:uninstall-k3s +``` +{%- endif %} diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/k3s.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/k3s.yaml new file mode 100644 index 00000000..f77dbe30 --- /dev/null +++ b/{{cookiecutter.project_slug}}/bootstrap-cluster/k3s.yaml @@ -0,0 +1,237 @@ +--- +version: '3' +env: + KUBECONFIG: ./{{ '{{.ENV}}' }}/kubeconfig + SSH_KEY: ./{{ '{{.ENV}}' }}/id_ed25519 + TFDIR: ../terraform/{{ '{{.ENV}}' }} + +tasks: + bootstrap: + desc: | + Run all tasks required to bootstrap k3s and Kubernetes cluster. + requires: + vars: [ENV] + cmds: + - task: save-node-ips + - task: setup-ssh-key + - task: install-ecr-credential-helper + - task: install-k3s + - task: fetch-kubeconfig + - task: store-kubeconfig + + save-node-ips: + desc: Save node IPs to files for later reference + requires: + vars: [ENV] + cmds: + - tofu -chdir=$TFDIR output control_plane_nodes_public_ips | tr -d '"' > {{ '{{.ENV}}' }}/public_ips.txt + - tofu -chdir=$TFDIR output control_plane_nodes_private_ips | tr -d '"' > {{ '{{.ENV}}' }}/private_ips.txt + + setup-ssh-key: + desc: Extract and save SSH key from terraform output + cmds: + - tofu -chdir={{ '{{.TFDIR}}' }} output -raw private_deploy_key > {{ '{{.SSH_KEY}}' }} + - chmod 600 $SSH_KEY + + ssh-server-node: + vars: + IP: + sh: head -n1 {{ '{{.ENV}}' }}/public_ips.txt + requires: + vars: [ENV] + cmds: + - TERM=xterm-256color ssh -oStrictHostKeyChecking=no -i {{ '{{.SSH_KEY}}' }} ubuntu@{{ '{{.IP}}' }} + + install-ecr-credential-helper: + desc: | + Install the ECR credential helper on all control plane nodes. + vars: + NODE_IPS: + sh: cat {{ '{{.ENV}}' }}/public_ips.txt + requires: + vars: [ENV] + cmds: + - | + for ip in $(echo "{{ '{{.NODE_IPS}}' }}"); do + echo "Installing ECR credential helper on $ip..." + # Download and install the ECR credential provider + ssh -oStrictHostKeyChecking=no -i {{ '{{.SSH_KEY}}' }} ubuntu@$ip \ + 'sudo wget https://artifacts.k8s.io/binaries/cloud-provider-aws/v1.29.0/linux/amd64/ecr-credential-provider-linux-amd64 -O /usr/local/bin/ecr-credential-provider && \ + sudo chmod +x /usr/local/bin/ecr-credential-provider' + + # Create credential provider config + ssh -oStrictHostKeyChecking=no -i {{ '{{.SSH_KEY}}' }} ubuntu@$ip \ + 'sudo mkdir -p /etc/rancher/k3s && \ + echo "apiVersion: kubelet.config.k8s.io/v1 + kind: CredentialProviderConfig + providers: + - name: ecr-credential-provider + matchImages: + - \"*.dkr.ecr.*.amazonaws.com\" + defaultCacheDuration: \"12h\" + apiVersion: credentialprovider.kubelet.k8s.io/v1" | sudo tee /etc/rancher/k3s/credential-provider-config.yaml' + done + + install-k3s: + desc: Install k3s on nodes + vars: + PUBLIC_IPS: + sh: cat {{ '{{.ENV}}' }}/public_ips.txt + PRIVATE_IPS: + sh: cat {{ '{{.ENV}}' }}/private_ips.txt + FIRST_PUBLIC_IP: + sh: head -n1 {{ '{{.ENV}}' }}/public_ips.txt + FIRST_PRIVATE_IP: + sh: head -n1 {{ '{{.ENV}}' }}/private_ips.txt + OTHER_PUBLIC_IPS: + sh: tail -n +2 {{ '{{.ENV}}' }}/public_ips.txt + OTHER_PRIVATE_IPS: + sh: tail -n +2 {{ '{{.ENV}}' }}/private_ips.txt + NODE_COUNT: + sh: wc -l < {{ '{{.ENV}}' }}/public_ips.txt + K3S_TOKEN: + sh: tr -dc A-Za-z0-9 </dev/urandom | head -c 13 + requires: + vars: [ENV] + silent: true + cmds: + - | + # Install first node + CLUSTER_INIT="" + if [ "{{ '{{.NODE_COUNT}}' }}" -gt 1 ]; then + CLUSTER_INIT="--cluster-init" + fi + ssh -oStrictHostKeyChecking=no -i {{ '{{.SSH_KEY}}' }} \ + ubuntu@{{ '{{.FIRST_PUBLIC_IP}}' }} \ + 'curl -sfL https://get.k3s.io | K3S_TOKEN={{ '{{.K3S_TOKEN}}' }} \ + INSTALL_K3S_EXEC="server {{ '{{.CLUSTER_INIT}}' }} \ + --tls-san {{ '{{.FIRST_PUBLIC_IP}}' }} --tls-san {{ '{{.FIRST_PRIVATE_IP}}' }} \ + --node-ip {{ '{{.FIRST_PRIVATE_IP}}' }} \ + --advertise-address {{ '{{.FIRST_PRIVATE_IP}}' }} \ + --disable=traefik \ + --image-credential-provider-config /etc/rancher/k3s/credential-provider-config.yaml \ + --image-credential-provider-bin-dir /usr/local/bin" \ + K3S_KUBECONFIG_MODE="644" sh -s -' + + # Wait briefly then check k3s service status + echo "Waiting 5s for k3s service to initialize on {{ '{{.FIRST_PUBLIC_IP}}' }}..." + sleep 5 + if ! ssh -oStrictHostKeyChecking=no -i {{ '{{.SSH_KEY}}' }} ubuntu@{{ '{{.FIRST_PUBLIC_IP}}' }} 'systemctl is-failed --quiet k3s'; then + echo "k3s service initialized successfully" + else + echo "k3s service failed to start properly" + exit 1 + fi + + - | + # Install other nodes if they exist + if [ "{{ '{{.NODE_COUNT}}' }}" -gt 1 ]; then + for ip in $(echo "{{ '{{.OTHER_PUBLIC_IPS}}' }}"); do + i=$((i+1)) + PUBLIC_IP=$(echo "{{ '{{.OTHER_PUBLIC_IPS}}' }}" | sed -n "${i}p") + PRIVATE_IP=$(echo "{{ '{{.OTHER_PRIVATE_IPS}}' }}" | sed -n "${i}p") + echo "Installing $PUBLIC_IP..." + ssh -oStrictHostKeyChecking=no -i {{ '{{.SSH_KEY}}' }} ubuntu@$PUBLIC_IP \ + 'curl -sfL https://get.k3s.io | K3S_TOKEN={{ '{{.K3S_TOKEN}}' }} \ + INSTALL_K3S_EXEC="server --server https://{{ '{{.FIRST_PRIVATE_IP}}' }}:6443 \ + --tls-san {{ '{{.FIRST_PUBLIC_IP}}' }} --tls-san {{ '{{.FIRST_PRIVATE_IP}}' }} \ + --node-ip '$PRIVATE_IP' \ + --disable=traefik \ + --image-credential-provider-config /etc/rancher/k3s/credential-provider-config.yaml \ + --image-credential-provider-bin-dir /usr/local/bin" \ + K3S_KUBECONFIG_MODE="644" sh -s -' + done + fi + + fetch-kubeconfig: + desc: Fetch and modify kubeconfig from first control plane node + requires: + vars: [ENV] + vars: + IP: + sh: head -n1 {{ '{{.ENV}}' }}/public_ips.txt + cmds: + - | + if [ -f {{ '{{.ENV}}' }}/kubeconfig ]; then + cp {{ '{{.ENV}}' }}/kubeconfig {{ '{{.ENV}}' }}/kubeconfig.bak.$(date +%Y%m%d_%H%M%S) + fi + scp -o StrictHostKeyChecking=no -i {{ '{{.SSH_KEY}}' }} ubuntu@{{ '{{.IP}}' }}:/etc/rancher/k3s/k3s.yaml {{ '{{.ENV}}' }}/kubeconfig + - sed -i'' -e "s/127.0.0.1/{{ '{{.IP}}' }}/g" {{ '{{.ENV}}' }}/kubeconfig + - sed -i'' -e "s/default/hotelnames-{{ '{{.ENV}}' }}/g" {{ '{{.ENV}}' }}/kubeconfig + - chmod 600 {{ '{{.ENV}}' }}/kubeconfig + + store-kubeconfig: + desc: | + Store the Kubernetes kubeconfig file in AWS Secrets Manager. + requires: + vars: [ENV] + cmds: + - | + aws secretsmanager create-secret \ + --name "{{ '{{.ENV}}' }}_kubeconfig" \ + --secret-string "$(base64 -w0 $KUBECONFIG)" + + delete-all-secrets: + desc: | + Delete all related secrets from AWS Secrets Manager. + requires: + vars: [ENV] + cmds: + - | + aws secretsmanager delete-secret \ + --secret-id "{{ '{{.ENV}}' }}_kubeconfig" \ + --force-delete-without-recovery + + reset-config: + desc: | + Remove all config files and delete secrets in AWS Secrets Manager + requires: + vars: [ENV] + cmds: + - task: delete_all_secrets + - cd {{ '{{.ENV}}' }} && rm -f kubeconfig + + kubeconfig: + desc: | + Retrieve the Kubeconfig for a given cluster + + Since the commands run in sub-shell you can eval the output to export + KUBECONFIG to your current shell: + + eval $(task k3s:kubeconfig) + silent: true + cmds: + - echo "export KUBECONFIG=$(pwd)/{{ '{{.ENV}}' }}/kubeconfig" + + uninstall-k3s: + desc: Uninstall k3s from all nodes + vars: + PUBLIC_IPS: + sh: cat {{ '{{.ENV}}' }}/public_ips.txt + requires: + vars: [ENV] + silent: true + cmds: + - | + for ip in $(echo "{{ '{{.PUBLIC_IPS}}' }}"); do + echo "Uninstalling k3s from $ip..." + ssh -oStrictHostKeyChecking=no -i {{ '{{.SSH_KEY}}' }} ubuntu@$ip \ + '/usr/local/bin/k3s-uninstall.sh' + done + + fetch-config: + desc: | + Fetch kubeconfig from AWS Secrets + Manager. + requires: + vars: [ENV] + cmds: + - | + if [ -f {{ '{{.ENV}}' }}/kubeconfig ]; then + cp {{ '{{.ENV}}' }}/kubeconfig {{ '{{.ENV}}' }}/kubeconfig.bak.$(date +%Y%m%d_%H%M%S) + fi + aws secretsmanager get-secret-value \ + --secret-id "{{ '{{.ENV}}' }}_kubeconfig" | \ + yq ".SecretString" | tr -d '"' | \ + base64 -d > ./{{ '{{.ENV}}' }}/kubeconfig + - chmod 600 {{ '{{.ENV}}' }}/kubeconfig diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/taskfile.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/taskfile.yaml index 1a0a2e4b..6eb7ecd1 100644 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/taskfile.yaml +++ b/{{cookiecutter.project_slug}}/bootstrap-cluster/taskfile.yaml @@ -4,7 +4,11 @@ dotenv: ['.env', '{{ "{{.ENV}}" }}/.env'] includes: argocd: ./argocd.yaml +{%- if cookiecutter.operating_system == "talos" %} talos: ./talos.yaml +{%- elif cookiecutter.operating_system == "k3s" %} + k3s: ./k3s.yaml +{%- endif %} tasks: default: diff --git a/{{cookiecutter.project_slug}}/terraform/README.md b/{{cookiecutter.project_slug}}/terraform/README.md index 04f3253a..06d53180 100644 --- a/{{cookiecutter.project_slug}}/terraform/README.md +++ b/{{cookiecutter.project_slug}}/terraform/README.md @@ -29,6 +29,7 @@ run the Terraform configurations. Ensure that you have installed AWS CLI version 2, as AWS SSO support is only available in version 2 and above. Create a new AWS profile in `~/.aws/config`. Here's an example of the `~/.aws/config` profile: + ``` [profile scaf] sso_start_url = https://sixfeetup.awsapps.com/start @@ -43,6 +44,7 @@ Note the `sso_role_name` setting above. Make sure to use a role that provides you with the necessary permissions to deploy infrastructure on your AWS account. Export the `AWS_PROFILE` environment variable and continue logging in: + ``` $ export AWS_PROFILE=scaf $ aws sso login @@ -50,6 +52,7 @@ $ aws sso login This should open your browser, allowing you to sign in to your AWS account. Upon successful login, you will see a message to confirm it: + ``` Successfully logged into Start URL: https://sixfeetup.awsapps.com/start ``` @@ -60,24 +63,27 @@ The first step is to bootstrap the Terraform state. This involves creating an S3 bucket and a DynamoDB table to manage the state and locking. 1. Navigate to the `bootstrap` directory: - ```bash - cd bootstrap - ``` + + ```bash + cd bootstrap + ``` 2. Initialize the Terraform configuration: - ```bash - terraform init - ``` + + ```bash + terraform init + ``` 3. Plan the Terraform configuration: - ```bash - terraform plan -out="tfplan.out" - ``` + + ```bash + terraform plan -out="tfplan.out" + ``` 4. Apply the Terraform configuration: - ```bash - terraform apply tfplan.out - ``` + ```bash + terraform apply tfplan.out + ``` ### Step 3: GitHub OIDC Provider @@ -85,24 +91,27 @@ After bootstrapping the state, the next step is to set up the GitHub OIDC provider. 1. Navigate to the `github` directory: - ```bash - cd ../github - ``` + + ```bash + cd ../github + ``` 2. Initialize the Terraform configuration: - ```bash - terraform init - ``` + + ```bash + terraform init + ``` 3. Plan the Terraform configuration: - ```bash - terraform plan -out="tfplan.out" - ``` + + ```bash + terraform plan -out="tfplan.out" + ``` 4. Apply the Terraform configuration: - ```bash - terraform apply tfplan.out - ``` + ```bash + terraform apply tfplan.out + ``` ### Step 4: Environment Configurations @@ -112,31 +121,33 @@ sandbox, staging). 1. Navigate to the desired environment directory (e.g., `prod`, `sandbox`, `staging`): - ```bash - cd ../<environment> - ``` + ```bash + cd ../<environment> + ``` 2. Initialize the Terraform configuration: - ```bash - terraform init - ``` + + ```bash + terraform init + ``` 3. Restrict the IPs allowed to manage the cluster. Edit - `<environment>/cluster.tf` and set the following variables: - ``` - kubectl_allowed_ips = "10.0.0.1/32,10.0.0.2/32" - talos_allowed_ips = "10.0.0.1/32,10.0.0.2/32" - ``` + `<environment>/cluster.tf` and set the following variables: + + ``` + admin_allowed_ips = "10.0.0.1/32,10.0.0.2/32" + ``` 4. Plan the Terraform configuration: - ```bash - terraform plan -out="tfplan.out" - ``` + + ```bash + terraform plan -out="tfplan.out" + ``` 5. Apply the Terraform configuration: - ```bash - terraform apply tfplan.out - ``` + ```bash + terraform apply tfplan.out + ``` ## Summary @@ -147,7 +158,6 @@ configurations: 2. Set up the GitHub OIDC provider (`github` directory). 3. Configure the desired environment (`prod`, `sandbox`, or `staging` directory). - Each step involves running `terraform init`, `terraform plan -out="tfplan.out"`, and `terraform apply tfplan.out`. diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/ec2.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/ec2.tf index f5af6687..dc055656 100644 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/ec2.tf +++ b/{{cookiecutter.project_slug}}/terraform/modules/base/ec2.tf @@ -1,8 +1,34 @@ -data "aws_ami" "talos" { +{% if cookiecutter.operating_system == "talos" %} +data "aws_ami" "os" { owners = ["540036508848"] # Sidero Labs most_recent = true name_regex = "^talos-v\\d+\\.\\d+\\.\\d+-${data.aws_availability_zones.available.id}-amd64$" } +{%- elif cookiecutter.operating_system == "k3s" %} +data "aws_ami" "os" { + most_recent = true + owners = ["099720109477"] # Canonical + filter { + name = "name" + values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] + } + + filter { + name = "virtualization-type" + values = ["hvm"] + } +} + +resource "tls_private_key" "deploy_key" { + algorithm = "ED25519" +} + +resource "aws_key_pair" "default_key" { + key_name = "hotelnames_deploy_key" + public_key = tls_private_key.deploy_key.public_key_openssh +} + +{%- endif %} locals { cluster_required_tags = { @@ -17,7 +43,7 @@ module "control_plane_nodes" { count = var.control_plane.num_instances name = "${var.cluster_name}-${count.index}" - ami = var.control_plane.ami_id == null ? data.aws_ami.talos.id : var.control_plane.ami_id + ami = var.control_plane.ami_id == null ? data.aws_ami.os.id : var.control_plane.ami_id monitoring = true instance_type = var.control_plane.instance_type iam_instance_profile = aws_iam_instance_profile.ec2_instance_profile.name @@ -26,6 +52,10 @@ module "control_plane_nodes" { create_iam_instance_profile = false tags = merge(local.common_tags, local.cluster_required_tags) +{%- if cookiecutter.operating_system == "k3s" %} + key_name = aws_key_pair.default_key.key_name +{%- endif %} + vpc_security_group_ids = [module.cluster_sg.security_group_id] } diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/outputs.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/outputs.tf index ada14deb..ce305c19 100644 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/outputs.tf +++ b/{{cookiecutter.project_slug}}/terraform/modules/base/outputs.tf @@ -25,6 +25,20 @@ output "amazon_ses_user_secret_key" { {% endif %} output "control_plane_nodes_public_ips" { - description = "The public ip addresses of the talos control plane nodes." + description = "The public ip addresses of the control plane nodes." value = join(",", module.control_plane_nodes.*.public_ip) } + +output "control_plane_nodes_private_ips" { + description = "The private ip addresses of the control plane nodes." + value = join(",", module.control_plane_nodes.*.private_ip) +} + +output "private_deploy_key" { + value = tls_private_key.deploy_key.private_key_openssh + sensitive = true +} + +output "public_deploy_key" { + value = tls_private_key.deploy_key.public_key_openssh +} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/security_groups.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/security_groups.tf index a5d33f82..f0df4dc7 100644 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/security_groups.tf +++ b/{{cookiecutter.project_slug}}/terraform/modules/base/security_groups.tf @@ -30,17 +30,26 @@ module "cluster_sg" { from_port = 6443 to_port = 6443 protocol = "tcp" - cidr_blocks = var.kubectl_allowed_ips + cidr_blocks = var.admin_allowed_ips description = "Kubernetes API Access" }, - # TODO: add cookiecutter.use_talos check +{% if cookiecutter.operating_system == "talos" %} { from_port = 50000 to_port = 50000 protocol = "tcp" - cidr_blocks = var.talosctl_allowed_ips + cidr_blocks = var.admin_allowed_ips description = "Talos API Access" }, +{%- elif cookiecutter.operating_system == "k3s" %} + { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = var.admin_allowed_ips + description = "Talos API Access" + }, +{%- endif %} ] egress_with_cidr_blocks = [ diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/variables.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/variables.tf index 1b321015..376a043f 100644 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/variables.tf +++ b/{{cookiecutter.project_slug}}/terraform/modules/base/variables.tf @@ -90,12 +90,13 @@ variable "cluster_vpc_cidr" { default = "172.16.0.0/16" } -# TODO: add cookiecutter.use_talos check +{% if cookiecutter.operating_system == "talos" %} variable "config_patch_files" { description = "Path to talos config path files that applies to all nodes" type = list(string) default = [] } +{%- endif %} variable "repo_name" { type = string @@ -121,19 +122,12 @@ variable "backend_ecr_repo" { default = "{{ cookiecutter.project_dash }}-sandbox-backend" } -variable "kubectl_allowed_ips" { +variable "admin_allowed_ips" { description = "A list of CIDR blocks that are allowed to access the kubernetes api" type = string default = "0.0.0.0/0" } -# TODO: add cookiecutter.use_talos check -variable "talosctl_allowed_ips" { - description = "A list of CIDR blocks that are allowed to access the talos api" - type = string - default = "0.0.0.0/0" -} - variable "tags" { type = map(string) default = {} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/versions.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/versions.tf index ecd58f1a..932fa456 100644 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/versions.tf +++ b/{{cookiecutter.project_slug}}/terraform/modules/base/versions.tf @@ -9,14 +9,6 @@ terraform { source = "siderolabs/talos" version = "0.5.0" } - helm = { - source = "hashicorp/helm" - version = "2.13.2" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "2.30.0" - } null = { source = "hashicorp/null" version = "3.2.2" @@ -25,9 +17,5 @@ terraform { source = "hashicorp/local" version = ">= 2.5.1" } - template = { - source = "hashicorp/template" - version = ">= 2.2.0" - } } } diff --git a/{{cookiecutter.project_slug}}/terraform/prod/cluster.tf b/{{cookiecutter.project_slug}}/terraform/prod/cluster.tf index 06f7fef5..7a3eb0bb 100644 --- a/{{cookiecutter.project_slug}}/terraform/prod/cluster.tf +++ b/{{cookiecutter.project_slug}}/terraform/prod/cluster.tf @@ -16,8 +16,7 @@ module "cluster" { # ami_id = "ami-09d22b42af049d453" } - # NB!: limit kubectl_allowed_ips and talos_allowed_ips to a set of trusted + # NB!: limit admin_allowed_ips to a set of trusted # public ip addresses. Both variables are comma separated lists of ips. - # kubectl_allowed_ips = "10.0.0.1/32,10.0.0.2/32" - # talos_allowed_ips = "10.0.0.1/32,10.0.0.2/32" + # admin_allowed_ips = "10.0.0.1/32,10.0.0.2/32" } diff --git a/{{cookiecutter.project_slug}}/terraform/sandbox/cluster.tf b/{{cookiecutter.project_slug}}/terraform/sandbox/cluster.tf index 736a5cf4..d1409e5b 100644 --- a/{{cookiecutter.project_slug}}/terraform/sandbox/cluster.tf +++ b/{{cookiecutter.project_slug}}/terraform/sandbox/cluster.tf @@ -17,8 +17,7 @@ module "cluster" { } - # NB!: limit kubectl_allowed_ips and talos_allowed_ips to a set of trusted + # NB!: limit admin_allowed_ips to a set of trusted # public ip addresses. Both variables are comma separated lists of ips. - # kubectl_allowed_ips = "10.0.0.1/32,10.0.0.2/32" - # talos_allowed_ips = "10.0.0.1/32,10.0.0.2/32" + # admin_allowed_ips = "10.0.0.1/32,10.0.0.2/32" } diff --git a/{{cookiecutter.project_slug}}/terraform/staging/cluster.tf b/{{cookiecutter.project_slug}}/terraform/staging/cluster.tf index 9efa34d0..30c18195 100644 --- a/{{cookiecutter.project_slug}}/terraform/staging/cluster.tf +++ b/{{cookiecutter.project_slug}}/terraform/staging/cluster.tf @@ -16,8 +16,7 @@ module "cluster" { # ami_id = "ami-09d22b42af049d453" } - # NB!: limit kubectl_allowed_ips and talos_allowed_ips to a set of trusted + # NB!: limit admin_allowed_ips to a set of trusted # public ip addresses. Both variables are comma separated lists of ips. - # kubectl_allowed_ips = "10.0.0.1/32,10.0.0.2/32" - # talos_allowed_ips = "10.0.0.1/32,10.0.0.2/32" + # admin_allowed_ips = "10.0.0.1/32,10.0.0.2/32" } From 2afd997423c9137592b494fb8e956ae56e8b3a8f Mon Sep 17 00:00:00 2001 From: semantic-release-bot <semantic-release-bot@martynus.net> Date: Fri, 27 Dec 2024 06:49:55 +0000 Subject: [PATCH 2/6] chore(release): 1.21.0 [skip ci] ## [1.21.0](https://github.com/sixfeetup/scaf/compare/v1.20.0...v1.21.0) (2024-12-27) ### Features * Add k3s as option for kubernetes install. close [#167](https://github.com/sixfeetup/scaf/issues/167) ([e753983](https://github.com/sixfeetup/scaf/commit/e7539836c8011ae3484d8e82ac5a43101e6c95e6)) --- CHANGELOG.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 621cad6f..1a696751 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [1.21.0](https://github.com/sixfeetup/scaf/compare/v1.20.0...v1.21.0) (2024-12-27) + +### Features + +* Add k3s as option for kubernetes install. close [#167](https://github.com/sixfeetup/scaf/issues/167) ([e753983](https://github.com/sixfeetup/scaf/commit/e7539836c8011ae3484d8e82ac5a43101e6c95e6)) + ## [1.20.0](https://github.com/sixfeetup/scaf/compare/v1.19.1...v1.20.0) (2024-12-10) ### Features diff --git a/package.json b/package.json index e42601c8..94f63ca4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scaf", - "version": "1.20.0", + "version": "1.21.0", "devDependencies": { "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", From 1027f887e64ed9e012eb6e5d72515986203e3f8a Mon Sep 17 00:00:00 2001 From: Muhammad Rehan <rehan@sixfeetup.com> Date: Mon, 23 Dec 2024 19:38:50 +0500 Subject: [PATCH 3/6] Update scaf to use template from scaf-template repo --- .github/workflows/setup-project.yaml | 2 +- scaf | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/setup-project.yaml b/.github/workflows/setup-project.yaml index 965efb4a..23898cec 100644 --- a/.github/workflows/setup-project.yaml +++ b/.github/workflows/setup-project.yaml @@ -64,5 +64,5 @@ jobs: git config --global user.email "setup-project--create@example.com" git config --global user.name "CI CD Setup Project" - REPO_URL="https://github.com/sixfeetup/scaf.git" + REPO_URL="https://github.com/rehan892/test-scaf-templates/" $HOME/.local/bin/scaf myproject --no-input --checkout $GITHUB_REF_NAME $REPO_URL diff --git a/scaf b/scaf index e45801ee..87f740d4 100755 --- a/scaf +++ b/scaf @@ -14,7 +14,11 @@ fi CHALLENGE_CONFIG_PATH=".scaf-challenge.json" # Default repository URL if none is provided -DEFAULT_REPO_URL="https://github.com/sixfeetup/scaf/" +DEFAULT_REPO_URL="https://github.com/rehan892/test-scaf-templates/" + +# Default template to use if none provided +DEFAULT_DIRECTORY="templates/sixfeetup-fullstack" +DIRECTORY_OPTION="--directory=\"$DEFAULT_DIRECTORY\"" # Ensure at least one argument is provided (for project_slug) if [ $# -lt 1 ]; then @@ -235,6 +239,7 @@ docker run --rm $DOCKER_RUN_OPTIONS -v "$(pwd):/home/scaf/out" \ cookiecutter \ $COOKIECUTTER_OPTIONS \ $REPO_URL \ + $DIRECTORY_OPTION \ project_slug="$COOKIECUTTER_SLUG" \ _challenge="$SCAF_CHALLENGE" From 423d52313f1e19539f371e8fe5e8aa57a7480e20 Mon Sep 17 00:00:00 2001 From: Muhammad Rehan <rehan@sixfeetup.com> Date: Mon, 23 Dec 2024 19:52:35 +0500 Subject: [PATCH 4/6] Update pipeline --- .github/workflows/setup-project.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup-project.yaml b/.github/workflows/setup-project.yaml index 23898cec..fb6a0f8e 100644 --- a/.github/workflows/setup-project.yaml +++ b/.github/workflows/setup-project.yaml @@ -65,4 +65,4 @@ jobs: git config --global user.name "CI CD Setup Project" REPO_URL="https://github.com/rehan892/test-scaf-templates/" - $HOME/.local/bin/scaf myproject --no-input --checkout $GITHUB_REF_NAME $REPO_URL + $HOME/.local/bin/scaf myproject --no-input $REPO_URL From 2821f0425eb7eecb7e58b787eaca0e60c53aded1 Mon Sep 17 00:00:00 2001 From: Muhammad Rehan <rehan@sixfeetup.com> Date: Mon, 23 Dec 2024 20:22:09 +0500 Subject: [PATCH 5/6] Add directory for template in docker build --- scaf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scaf b/scaf index 87f740d4..d5e2356c 100755 --- a/scaf +++ b/scaf @@ -18,7 +18,6 @@ DEFAULT_REPO_URL="https://github.com/rehan892/test-scaf-templates/" # Default template to use if none provided DEFAULT_DIRECTORY="templates/sixfeetup-fullstack" -DIRECTORY_OPTION="--directory=\"$DEFAULT_DIRECTORY\"" # Ensure at least one argument is provided (for project_slug) if [ $# -lt 1 ]; then @@ -239,7 +238,7 @@ docker run --rm $DOCKER_RUN_OPTIONS -v "$(pwd):/home/scaf/out" \ cookiecutter \ $COOKIECUTTER_OPTIONS \ $REPO_URL \ - $DIRECTORY_OPTION \ + --directory="$DEFAULT_DIRECTORY" \ project_slug="$COOKIECUTTER_SLUG" \ _challenge="$SCAF_CHALLENGE" From e8578260b54102091b2692a18e6fe2b2f7ab2ada Mon Sep 17 00:00:00 2001 From: Muhammad Rehan <rehan@sixfeetup.com> Date: Mon, 30 Dec 2024 16:14:49 +0500 Subject: [PATCH 6/6] Move project template to new repo --- .github/workflows/setup-project.yaml | 2 +- cookiecutter.json | 33 - scaf | 2 +- {{cookiecutter.project_slug}}/.envrc | 15 - .../.github/workflows/main.yaml | 140 - {{cookiecutter.project_slug}}/.gitignore | 66 - .../.pre-commit-config.yaml | 34 - {{cookiecutter.project_slug}}/.yamlfmt | 5 - {{cookiecutter.project_slug}}/.yamllint | 29 - {{cookiecutter.project_slug}}/Makefile | 183 - {{cookiecutter.project_slug}}/README.md | 31 - {{cookiecutter.project_slug}}/Tiltfile | 62 - .../argocd/base/argocd/app.yaml | 33 - .../argocd/base/argocd/kustomization.yaml | 5 - .../argocd/base/cert-manager/app.yaml | 33 - .../base/cert-manager/kustomization.yaml | 5 - .../argocd/base/cloudnative-pg/app.yaml | 33 - .../base/cloudnative-pg/kustomization.yaml | 5 - .../argocd/base/ingress/app.yaml | 28 - .../argocd/base/ingress/kustomization.yaml | 5 - .../base/kube-prometheus-stack/app.yaml | 62 - .../kube-prometheus-stack/kustomization.yaml | 5 - .../local-path-provisioner/kustomization.yaml | 36 - .../argocd/base/reflector/app.yaml | 28 - .../argocd/base/reflector/kustomization.yaml | 5 - .../argocd/base/sealed-secrets/app.yaml | 31 - .../base/sealed-secrets/kustomization.yaml | 5 - .../argocd/base/traefik/app.yaml | 37 - .../argocd/base/traefik/kustomization.yaml | 5 - .../{{ cookiecutter.project_slug }}/app.yaml | 26 - .../kustomization.yaml | 5 - .../argocd/prod/apps/kustomization.yaml | 25 - .../argocd/prod/ingress/kustomization.yaml | 35 - .../argocd/sandbox/apps/kustomization.yaml | 40 - .../sandbox/ingress/cert-manager-issuer.yaml | 33 - .../argocd/sandbox/ingress/certificates.yaml | 15 - .../argocd/sandbox/ingress/ingress.yaml | 59 - .../argocd/sandbox/ingress/kustomization.yaml | 6 - .../backend/Dockerfile | 106 - .../backend/config/__init__.py | 7 - .../backend/config/asgi.py | 16 - .../backend/config/schema.py | 11 - .../backend/config/settings/__init__.py | 0 .../backend/config/settings/base.py | 347 - .../backend/config/settings/local.py | 75 - .../backend/config/settings/production.py | 192 - .../backend/config/settings/test.py | 48 - .../backend/config/urls.py | 59 - .../backend/config/wsgi.py | 38 - .../backend/env.example | 21 - .../backend/manage.py | 23 - .../backend/requirements/base.in | 29 - .../backend/requirements/local.in | 9 - .../backend/requirements/production.in | 20 - .../backend/requirements/tests.in | 15 - .../{{cookiecutter.project_slug}}/__init__.py | 7 - .../{{cookiecutter.project_slug}}/celery.py | 17 - .../challenge/__init__.py | 0 .../challenge/admin.py | 8 - .../challenge/apps.py | 16 - .../challenge/migrations/0001_initial.py | 25 - .../challenge/migrations/__init__.py | 0 .../challenge/models.py | 13 - .../challenge/utils.py | 37 - .../{{cookiecutter.project_slug}}/conftest.py | 24 - .../contrib/__init__.py | 5 - .../contrib/sites/__init__.py | 5 - .../contrib/sites/migrations/0001_initial.py | 41 - .../migrations/0002_alter_domain_unique.py | 19 - .../0003_set_site_domain_and_name.py | 33 - .../contrib/sites/migrations/__init__.py | 5 - .../static/css/project.css | 13 - .../static/fonts/.gitkeep | 0 .../static/images/favicons/favicon.ico | Bin 8348 -> 0 bytes .../static/js/project.js | 1 - .../static/sass/project.scss | 35 - .../templates/403.html | 9 - .../templates/404.html | 9 - .../templates/500.html | 13 - .../templates/account/account_inactive.html | 12 - .../templates/account/base.html | 11 - .../templates/account/email.html | 80 - .../templates/account/email_confirm.html | 32 - .../templates/account/login.html | 48 - .../templates/account/logout.html | 22 - .../templates/account/password_change.html | 17 - .../templates/account/password_reset.html | 26 - .../account/password_reset_done.html | 17 - .../account/password_reset_from_key.html | 25 - .../account/password_reset_from_key_done.html | 10 - .../templates/account/password_set.html | 17 - .../templates/account/signup.html | 23 - .../templates/account/signup_closed.html | 12 - .../templates/account/verification_sent.html | 13 - .../account/verified_email_required.html | 24 - .../templates/base.html | 106 - .../templates/pages/about.html | 1 - .../templates/pages/home.html | 1 - .../templates/users/user_detail.html | 36 - .../templates/users/user_form.html | 17 - .../users/__init__.py | 0 .../users/adapters.py | 16 - .../users/admin.py | 16 - .../users/apps.py | 13 - .../users/forms.py | 29 - .../users/migrations/0001_initial.py | 131 - .../users/migrations/__init__.py | 0 .../users/models.py | 13 - .../users/mutations.py | 35 - .../users/queries.py | 13 - .../users/tasks.py | 11 - .../users/tests/__init__.py | 0 .../users/tests/factories.py | 32 - .../users/tests/test_forms.py | 40 - .../users/tests/test_graphql_views.py | 122 - .../users/tests/test_models.py | 9 - .../users/tests/test_tasks.py | 16 - .../users/tests/test_urls.py | 24 - .../users/tests/test_views.py | 79 - .../users/types.py | 19 - .../users/urls.py | 14 - .../users/views.py | 47 - .../utils/__init__.py | 0 .../utils/cloud_storage.py | 10 - .../utils/context_processors.py | 5 - .../utils/debugger.py | 34 - .../utils/healthcheck.py | 67 - .../bitbucket-pipelines.yml | 69 - .../bootstrap-cluster/.gitignore | 11 - .../bootstrap-cluster/README.md | 288 - .../bootstrap-cluster/argocd.yaml | 80 - .../patches/patch-control-plane.yaml | 10 - .../patches/patch-ecr-credential-helper.yaml | 15 - .../patches/patch-machine.yaml | 8 - .../bootstrap-cluster/prod/.env | 2 - .../bootstrap-cluster/root-app.template.yaml | 27 - .../bootstrap-cluster/sandbox/.env | 2 - .../bootstrap-cluster/staging/.env | 2 - .../bootstrap-cluster/talos.yaml | 202 - .../bootstrap-cluster/taskfile.yaml | 19 - {{cookiecutter.project_slug}}/docs/README.md | 17 - .../docs/architecture.md | 3 - {{cookiecutter.project_slug}}/docs/debug.md | 30 - .../docs/deployment.md | 10 - .../docs/development.md | 71 - .../docs/monitoring.md | 91 - .../docs/project-overview.md | 3 - {{cookiecutter.project_slug}}/docs/qa.md | 3 - {{cookiecutter.project_slug}}/docs/secrets.md | 33 - {{cookiecutter.project_slug}}/docs/sentry.md | 51 - .../frontend/.dockerignore | 11 - .../frontend/.env.local.example | 3 - .../frontend/.eslintrc.json | 67 - .../frontend/.gitignore | 38 - .../frontend/.husky/pre-push | 9 - .../frontend/.prettierignore | 5 - .../frontend/.prettierrc | 13 - .../frontend/Dockerfile | 17 - .../frontend/README.md | 39 - .../__generated__/fragment-masking.ts | 87 - .../frontend/__generated__/gql.ts | 42 - .../frontend/__generated__/graphql.ts | 111 - .../frontend/__generated__/index.ts | 2 - .../frontend/__tests__/about.test.tsx | 23 - .../frontend/codegen.ts | 19 - .../frontend/components/ErrorBoundary.tsx | 48 - .../frontend/components/Footer.tsx | 24 - .../frontend/components/Layout.tsx | 19 - .../frontend/components/NavBar.tsx | 18 - .../frontend/lib/apolloClient.ts | 87 - .../frontend/next.config.mjs | 6 - .../frontend/package-lock.json | 11853 ---------------- .../frontend/package.json | 58 - .../frontend/pages/404.tsx | 8 - .../frontend/pages/500.tsx | 3 - .../frontend/pages/_app.tsx | 21 - .../frontend/pages/_document.tsx | 13 - .../frontend/pages/about.tsx | 31 - .../frontend/pages/api/hello.ts | 10 - .../frontend/pages/index.tsx | 25 - .../frontend/postcss.config.mjs | 8 - .../frontend/public/favicon.ico | Bin 25931 -> 0 bytes .../frontend/public/scaf-logo.png | Bin 47188 -> 0 bytes .../frontend/styles/globals.css | 3 - .../frontend/tailwind.config.ts | 11 - .../frontend/tsconfig.json | 21 - .../frontend/utils/test-utils.tsx | 18 - .../frontend/vitest.config.ts | 16 - .../frontend/vitest.setup.ts | 3 - .../k8s/_monitoring/django-logs-table.yaml | 190 - .../k8s/_monitoring/loki-stack-values.yaml | 33 - .../k8s/argocd/README.md | 45 - .../k8s/base/app.configmap.yaml | 40 - .../k8s/base/celery.yaml | 41 - .../k8s/base/django.yaml | 82 - .../k8s/base/flower.yaml | 31 - .../k8s/base/frontend.yaml | 46 - .../k8s/base/ingress.yaml | 65 - .../k8s/base/kustomization.yaml | 11 - .../k8s/base/redis.yaml | 36 - .../k8s/local/kustomization.yaml | 34 - .../k8s/local/postgres.yaml | 78 - .../k8s/local/secrets.yaml | 9 - .../k8s/mailhog/kustomization.yaml | 5 - .../k8s/mailhog/mailhog.yaml | 42 - .../k8s/prod/kustomization.yaml | 63 - .../k8s/sandbox/certificate.yaml | 12 - .../k8s/sandbox/ingress-route.yaml | 63 - .../k8s/sandbox/kustomization.yaml | 85 - .../k8s/sandbox/postgres.cnpg.yaml | 14 - .../k8s/templates/secrets.yaml.template | 15 - {{cookiecutter.project_slug}}/mkdocs.yml | 43 - .../terraform/.gitignore | 4 - .../terraform/README.md | 165 - .../terraform/bootstrap/init.tf | 46 - .../terraform/github/oidc.tf | 63 - .../terraform/modules/base/Makefile | 63 - .../terraform/modules/base/acm.tf | 22 - .../terraform/modules/base/backend.tf | 9 - .../terraform/modules/base/cloudfront.tf | 110 - .../terraform/modules/base/ec2-iam-role.tf | 116 - .../terraform/modules/base/ec2.tf | 61 - .../terraform/modules/base/ecr.tf | 57 - .../terraform/modules/base/elb.tf | 44 - .../terraform/modules/base/github-iam-role.tf | 43 - .../terraform/modules/base/iam.tf | 31 - .../terraform/modules/base/locals.tf | 8 - .../terraform/modules/base/outputs.tf | 44 - .../terraform/modules/base/route53.tf | 70 - .../terraform/modules/base/s3.tf | 88 - .../terraform/modules/base/security_groups.tf | 61 - .../terraform/modules/base/variables.tf | 134 - .../terraform/modules/base/versions.tf | 21 - .../terraform/modules/base/vpc.tf | 22 - .../modules/global_variables/main.tf | 26 - .../terraform/prod/backend.tf | 10 - .../terraform/prod/cluster.tf | 22 - .../terraform/prod/outputs.tf | 30 - .../terraform/sandbox/backend.tf | 14 - .../terraform/sandbox/cluster.tf | 23 - .../terraform/sandbox/outputs.tf | 30 - .../terraform/staging/backend.tf | 10 - .../terraform/staging/cluster.tf | 22 - .../terraform/staging/outputs.tf | 48 - 244 files changed, 2 insertions(+), 20338 deletions(-) delete mode 100644 cookiecutter.json delete mode 100644 {{cookiecutter.project_slug}}/.envrc delete mode 100644 {{cookiecutter.project_slug}}/.github/workflows/main.yaml delete mode 100644 {{cookiecutter.project_slug}}/.gitignore delete mode 100644 {{cookiecutter.project_slug}}/.pre-commit-config.yaml delete mode 100644 {{cookiecutter.project_slug}}/.yamlfmt delete mode 100644 {{cookiecutter.project_slug}}/.yamllint delete mode 100644 {{cookiecutter.project_slug}}/Makefile delete mode 100644 {{cookiecutter.project_slug}}/README.md delete mode 100644 {{cookiecutter.project_slug}}/Tiltfile delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/argocd/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/argocd/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/cert-manager/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/cert-manager/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/cloudnative-pg/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/cloudnative-pg/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/ingress/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/ingress/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/kube-prometheus-stack/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/kube-prometheus-stack/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/local-path-provisioner/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/reflector/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/reflector/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/sealed-secrets/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/sealed-secrets/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/traefik/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/traefik/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/{{ cookiecutter.project_slug }}/app.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/base/{{ cookiecutter.project_slug }}/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/prod/apps/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/prod/ingress/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/sandbox/apps/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/sandbox/ingress/cert-manager-issuer.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/sandbox/ingress/certificates.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/sandbox/ingress/ingress.yaml delete mode 100644 {{cookiecutter.project_slug}}/argocd/sandbox/ingress/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/backend/Dockerfile delete mode 100644 {{cookiecutter.project_slug}}/backend/config/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/asgi.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/schema.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/settings/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/settings/base.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/settings/local.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/settings/production.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/settings/test.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/urls.py delete mode 100644 {{cookiecutter.project_slug}}/backend/config/wsgi.py delete mode 100644 {{cookiecutter.project_slug}}/backend/env.example delete mode 100755 {{cookiecutter.project_slug}}/backend/manage.py delete mode 100644 {{cookiecutter.project_slug}}/backend/requirements/base.in delete mode 100644 {{cookiecutter.project_slug}}/backend/requirements/local.in delete mode 100644 {{cookiecutter.project_slug}}/backend/requirements/production.in delete mode 100644 {{cookiecutter.project_slug}}/backend/requirements/tests.in delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/celery.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/admin.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/apps.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/migrations/0001_initial.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/migrations/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/models.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/utils.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/conftest.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0001_initial.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0002_alter_domain_unique.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0003_set_site_domain_and_name.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/css/project.css delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/fonts/.gitkeep delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/images/favicons/favicon.ico delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/js/project.js delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/sass/project.scss delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/403.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/404.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/500.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/account_inactive.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/base.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/email.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/email_confirm.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/login.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/logout.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_change.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_done.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_set.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/signup.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/signup_closed.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/verification_sent.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/verified_email_required.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/base.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/pages/about.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/pages/home.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/users/user_detail.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/users/user_form.html delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/adapters.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/admin.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/apps.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/forms.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/migrations/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/models.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/mutations.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/queries.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tasks.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/factories.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_forms.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_graphql_views.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_models.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_tasks.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_urls.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_views.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/types.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/urls.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/views.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/__init__.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/cloud_storage.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/context_processors.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/debugger.py delete mode 100644 {{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/healthcheck.py delete mode 100644 {{cookiecutter.project_slug}}/bitbucket-pipelines.yml delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/.gitignore delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/README.md delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/argocd.yaml delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-control-plane.yaml delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-ecr-credential-helper.yaml delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-machine.yaml delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/prod/.env delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/root-app.template.yaml delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/sandbox/.env delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/staging/.env delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/talos.yaml delete mode 100644 {{cookiecutter.project_slug}}/bootstrap-cluster/taskfile.yaml delete mode 100644 {{cookiecutter.project_slug}}/docs/README.md delete mode 100644 {{cookiecutter.project_slug}}/docs/architecture.md delete mode 100644 {{cookiecutter.project_slug}}/docs/debug.md delete mode 100644 {{cookiecutter.project_slug}}/docs/deployment.md delete mode 100644 {{cookiecutter.project_slug}}/docs/development.md delete mode 100644 {{cookiecutter.project_slug}}/docs/monitoring.md delete mode 100644 {{cookiecutter.project_slug}}/docs/project-overview.md delete mode 100644 {{cookiecutter.project_slug}}/docs/qa.md delete mode 100644 {{cookiecutter.project_slug}}/docs/secrets.md delete mode 100644 {{cookiecutter.project_slug}}/docs/sentry.md delete mode 100644 {{cookiecutter.project_slug}}/frontend/.dockerignore delete mode 100644 {{cookiecutter.project_slug}}/frontend/.env.local.example delete mode 100644 {{cookiecutter.project_slug}}/frontend/.eslintrc.json delete mode 100644 {{cookiecutter.project_slug}}/frontend/.gitignore delete mode 100644 {{cookiecutter.project_slug}}/frontend/.husky/pre-push delete mode 100644 {{cookiecutter.project_slug}}/frontend/.prettierignore delete mode 100644 {{cookiecutter.project_slug}}/frontend/.prettierrc delete mode 100644 {{cookiecutter.project_slug}}/frontend/Dockerfile delete mode 100644 {{cookiecutter.project_slug}}/frontend/README.md delete mode 100644 {{cookiecutter.project_slug}}/frontend/__generated__/fragment-masking.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/__generated__/gql.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/__generated__/graphql.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/__generated__/index.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/__tests__/about.test.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/codegen.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/components/ErrorBoundary.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/components/Footer.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/components/Layout.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/components/NavBar.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/lib/apolloClient.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/next.config.mjs delete mode 100644 {{cookiecutter.project_slug}}/frontend/package-lock.json delete mode 100644 {{cookiecutter.project_slug}}/frontend/package.json delete mode 100644 {{cookiecutter.project_slug}}/frontend/pages/404.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/pages/500.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/pages/_app.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/pages/_document.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/pages/about.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/pages/api/hello.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/pages/index.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/postcss.config.mjs delete mode 100644 {{cookiecutter.project_slug}}/frontend/public/favicon.ico delete mode 100644 {{cookiecutter.project_slug}}/frontend/public/scaf-logo.png delete mode 100644 {{cookiecutter.project_slug}}/frontend/styles/globals.css delete mode 100644 {{cookiecutter.project_slug}}/frontend/tailwind.config.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/tsconfig.json delete mode 100644 {{cookiecutter.project_slug}}/frontend/utils/test-utils.tsx delete mode 100644 {{cookiecutter.project_slug}}/frontend/vitest.config.ts delete mode 100644 {{cookiecutter.project_slug}}/frontend/vitest.setup.ts delete mode 100644 {{cookiecutter.project_slug}}/k8s/_monitoring/django-logs-table.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/_monitoring/loki-stack-values.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/argocd/README.md delete mode 100644 {{cookiecutter.project_slug}}/k8s/base/app.configmap.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/base/celery.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/base/django.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/base/flower.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/base/frontend.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/base/ingress.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/base/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/base/redis.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/local/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/local/postgres.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/local/secrets.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/mailhog/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/mailhog/mailhog.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/prod/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/sandbox/certificate.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/sandbox/ingress-route.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/sandbox/kustomization.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/sandbox/postgres.cnpg.yaml delete mode 100644 {{cookiecutter.project_slug}}/k8s/templates/secrets.yaml.template delete mode 100644 {{cookiecutter.project_slug}}/mkdocs.yml delete mode 100644 {{cookiecutter.project_slug}}/terraform/.gitignore delete mode 100644 {{cookiecutter.project_slug}}/terraform/README.md delete mode 100644 {{cookiecutter.project_slug}}/terraform/bootstrap/init.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/github/oidc.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/Makefile delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/acm.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/backend.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/cloudfront.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/ec2-iam-role.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/ec2.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/ecr.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/elb.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/github-iam-role.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/iam.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/locals.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/outputs.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/route53.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/s3.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/security_groups.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/variables.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/versions.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/base/vpc.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/modules/global_variables/main.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/prod/backend.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/prod/cluster.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/prod/outputs.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/sandbox/backend.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/sandbox/cluster.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/sandbox/outputs.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/staging/backend.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/staging/cluster.tf delete mode 100644 {{cookiecutter.project_slug}}/terraform/staging/outputs.tf diff --git a/.github/workflows/setup-project.yaml b/.github/workflows/setup-project.yaml index fb6a0f8e..0f67b501 100644 --- a/.github/workflows/setup-project.yaml +++ b/.github/workflows/setup-project.yaml @@ -64,5 +64,5 @@ jobs: git config --global user.email "setup-project--create@example.com" git config --global user.name "CI CD Setup Project" - REPO_URL="https://github.com/rehan892/test-scaf-templates/" + REPO_URL="https://github.com/sixfeetup/scaf-templates.git/" $HOME/.local/bin/scaf myproject --no-input $REPO_URL diff --git a/cookiecutter.json b/cookiecutter.json deleted file mode 100644 index 9f9bfb6d..00000000 --- a/cookiecutter.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "project_name": "My Awesome Scaf Project", - "project_slug": "{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_')|replace('.', '_')|trim() }}", - "project_dash": "{{ cookiecutter.project_name.lower()|replace(' ', '-')|replace('_', '-')|replace('.', '-')|trim() }}", - "description": "Behold My Awesome Project!", - "author_name": "Joe Scaf", - "domain_name": "sixfeetup.com", - "email": "{{ cookiecutter.author_name.lower()|replace(' ', '-') }}@{{ cookiecutter.domain_name }}", - "version": "0.1.0", - "timezone": "US/Eastern", - "aws_region": "us-east-1", - "aws_account_id": "000000000000", - "create_nextjs_frontend": "y", - "debug": "n", - "mail_service": ["Mailgun", "Amazon SES", "Other SMTP"], - "operating_system": ["k3s", "talos"], - "_challenge": "n", - "use_celery": "n", - "use_sentry": "n", - "source_control_provider": ["github.com", "bitbucket.org", "none"], - "source_control_organization_slug": "sixfeetup", - "__prompts__": { - "source_control_organization_slug": "What is the organization slug for the source control provider?", - "source_control_provider": { - "__prompt__": "Which source control provider do you want to use?", - "bitbucket": "Bitbucket", - "github": "Github", - "none": "No source control provider" - } - }, - "repo_name": "{{ cookiecutter.project_slug }}", - "repo_url": "git@{{ cookiecutter.source_control_provider }}:{{ cookiecutter.source_control_organization_slug }}/{{ cookiecutter.project_slug }}.git" -} diff --git a/scaf b/scaf index d5e2356c..7f1f63c1 100755 --- a/scaf +++ b/scaf @@ -14,7 +14,7 @@ fi CHALLENGE_CONFIG_PATH=".scaf-challenge.json" # Default repository URL if none is provided -DEFAULT_REPO_URL="https://github.com/rehan892/test-scaf-templates/" +DEFAULT_REPO_URL="https://github.com/sixfeetup/scaf-templates.git" # Default template to use if none provided DEFAULT_DIRECTORY="templates/sixfeetup-fullstack" diff --git a/{{cookiecutter.project_slug}}/.envrc b/{{cookiecutter.project_slug}}/.envrc deleted file mode 100644 index 311b821e..00000000 --- a/{{cookiecutter.project_slug}}/.envrc +++ /dev/null @@ -1,15 +0,0 @@ -# read the secrets from 1Password -# strip whitespace from the value -export AWS_S3_ACCESS_KEY_ID="op://{{ cookiecutter.project_name }}/AWS_S3_ACCESS_KEY_ID/token" -export AWS_S3_SECRET_ACCESS_KEY="op://{{ cookiecutter.project_name }}/AWS_S3_SECRET_ACCESS_KEY/token" -export AWS_SES_ACCESS_KEY_ID="op://{{ cookiecutter.project_name }}/AWS_SES_ACCESS_KEY_ID/token" -export AWS_SES_SECRET_ACCESS_KEY="op://{{ cookiecutter.project_name }}/AWS_SES_SECRET_ACCESS_KEY/token" -export POSTGRES_PASSWORD="op://{{ cookiecutter.project_name }}/POSTGRES_DB/password" -export POSTGRES_USER="op://{{ cookiecutter.project_name }}/POSTGRES_DB/username" -# use sandbox host for secrets generation -export POSTGRES_HOST=postgres -export DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}/{{ cookiecutter.project_slug }} -export DJANGO_SECRET_KEY="op://{{ cookiecutter.project_name }}/DJANGO_SECRET_KEY/token" -{%- if cookiecutter.mail_service == 'Mailgun' %} -# Mailgun api key -export MAILGUN_API_KEY="op://{{ cookiecutter.project_name }}/MAILGUN_API_KEY/token"{%- endif %} diff --git a/{{cookiecutter.project_slug}}/.github/workflows/main.yaml b/{{cookiecutter.project_slug}}/.github/workflows/main.yaml deleted file mode 100644 index 4a586a71..00000000 --- a/{{cookiecutter.project_slug}}/.github/workflows/main.yaml +++ /dev/null @@ -1,140 +0,0 @@ -name: Main Workflow - -on: [ push, pull_request ] - -env: - AWS_REGION: ${{ '{{ vars.AWS_REGION }}' }} - AWS_ACCOUNT_ID: ${{ '{{ vars.AWS_ACCOUNT_ID }}' }} - -jobs: - check-lint-and-formatting: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 - with: - python-version: "3.10" - - name: Check lint and formatting - run: make check-lint-and-formatting -{% if cookiecutter.create_nextjs_frontend == 'y' %} - check-lint-and-test-frontend: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 - with: - node-version: '20' - - name: Frontend Lint & Typecheck & Test - run: make check-lint-and-test-frontend - test-frontend: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 - with: - node-version: '20' - - name: Frontend Unit Tests - run: CI=true make frontend-test -{% endif %} - backend-test: - runs-on: ubuntu-latest - - services: - postgres: - image: postgres:16 - env: - POSTGRES_DB: {{ cookiecutter.project_slug }} - POSTGRES_USER: {{ cookiecutter.project_slug }} - POSTGRES_PASSWORD: TESTPASSWORD - # Set health checks to wait until postgres has started - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - ports: - - 5432:5432 - -{% if cookiecutter.use_celery == 'y' %} - redis: - image: redis - options: >- - --health-cmd "redis-cli ping" - --health-interval 10s - --health-timeout 5s - --health-retries 5 -{% endif %} - - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 - with: - python-version: "3.10" - - name: Run backend tests - run: CI=true make backend-test - env: - DATABASE_URL: postgresql://{{ cookiecutter.project_slug }}:TESTPASSWORD@localhost:5432/{{ cookiecutter.project_slug }} - POSTGRES_HOST: postgres - POSTGRES_PORT: 5432 -{% if cookiecutter.use_celery == 'y' %} CELERY_BROKER_URL: redis://127.0.0.1:6379/0{% endif %} - - build-and-push-images: - if: github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - needs: [check-lint-and-formatting, backend-test] - - permissions: - id-token: write - contents: write - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ '{{secrets.GITHUB_TOKEN}}' }} - persist-credentials: false - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Configure AWS credentials from OIDC - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: arn:aws:iam::${{ '{{ env.AWS_ACCOUNT_ID }}' }}:role/{{ cookiecutter.project_slug }}-github-oidc-role - aws-region: ${{ '{{ env.AWS_REGION }}' }} - - - name: Log in to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v1 - - - name: Set environment variables - run: | - echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - echo "BRANCH_NAME=$(echo ${{ '{{ github.ref }}' }} | sed s,refs/heads/,, | sed s,/,-,g)" >> $GITHUB_ENV - export TARGET_ENV=$(if [ "$BRANCH_NAME" = "main" ]; then echo "prod"; else echo "sandbox"; fi) - echo "TARGET_ENV=$TARGET_ENV" >> $GITHUB_ENV - echo "ECR_REPO_BACKEND=${{ '{{ env.AWS_ACCOUNT_ID }}' }}.dkr.ecr.${{ '{{ env.AWS_REGION }}' }}.amazonaws.com/{{ cookiecutter.project_dash }}-$TARGET_ENV-backend" >> $GITHUB_ENV - - - name: Build and push backend image - uses: docker/build-push-action@v5 - with: - context: ./backend - push: true - tags: ${{ '{{ env.ECR_REPO_BACKEND }}' }}:${{ '{{ env.SHORT_SHA }}' }},${{ '{{ env.ECR_REPO_BACKEND }}' }}:${{ '{{ env.BRANCH_NAME }}' }} - - - name: Tag Images - run: | - cd k8s/$TARGET_ENV - kustomize edit set image backend=$ECR_REPO_BACKEND:$SHORT_SHA - - - name: Commit & Push to GitHub - run: | - git config user.email "$GITHUB_EMAIL" - git config user.name "GitHub User" - git add k8s/$TARGET_ENV/kustomization.yaml - git commit -m "Update $TARGET_ENV image to $SHORT_SHA [skip ci]" - git push diff --git a/{{cookiecutter.project_slug}}/.gitignore b/{{cookiecutter.project_slug}}/.gitignore deleted file mode 100644 index cddeeba0..00000000 --- a/{{cookiecutter.project_slug}}/.gitignore +++ /dev/null @@ -1,66 +0,0 @@ -# These are some examples of commonly ignored file patterns. -# You should customize this list as applicable to your project. -# Learn more about .gitignore: -# https://www.atlassian.com/git/tutorials/saving-changes/gitignore - -# Node artifact files -node_modules/ -dist/ - -# Compiled Java class files -*.class - -# Compiled Python bytecode -*.py[cod] - -# Log files -*.log - -# Package files -*.jar - -# Maven -target/ -dist/ - -# JetBrains IDE -.idea/ - -# Unit test reports -TEST*.xml -.coverage - -# Generated by MacOS -.DS_Store - -# Generated by Windows -Thumbs.db - -# Applications -*.app -*.exe -*.war - -# Large media files -*.mp4 -*.tiff -*.avi -*.flv -*.mov -*.wmv - -docker-compose.override.yml - -# Environment files -env - -# vs code -.vscode/ -.history/ - -# terraform files -**/.terraform/* -*.tfstate -*.tfstate.* -*.tfvars -*.tfvars.json diff --git a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml b/{{cookiecutter.project_slug}}/.pre-commit-config.yaml deleted file mode 100644 index 2b8f4df0..00000000 --- a/{{cookiecutter.project_slug}}/.pre-commit-config.yaml +++ /dev/null @@ -1,34 +0,0 @@ -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 - hooks: - - id: check-case-conflict - - id: check-merge-conflict - - id: debug-statements - exclude: ^backend/{{ cookiecutter.project_slug }}/utils/debugger.py - - id: detect-aws-credentials - args: ["--allow-missing-credentials"] - - id: detect-private-key - - - repo: https://github.com/psf/black - rev: 23.9.1 - hooks: - - id: black - - - repo: https://github.com/pycqa/isort - rev: 5.12.0 - hooks: - - id: isort - args: ["--profile", "black", "--filter-files"] - - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: 'v0.0.290' - hooks: - - id: ruff - args: ["--ignore", "E501"] - - - repo: https://github.com/PyCQA/bandit - rev: 1.7.5 - hooks: - - id: bandit - args: ["-ll"] diff --git a/{{cookiecutter.project_slug}}/.yamlfmt b/{{cookiecutter.project_slug}}/.yamlfmt deleted file mode 100644 index f77b07e0..00000000 --- a/{{cookiecutter.project_slug}}/.yamlfmt +++ /dev/null @@ -1,5 +0,0 @@ -formatter: - type: basic - include_document_start: false - drop_merge_tag: true - max_line_length: 0 diff --git a/{{cookiecutter.project_slug}}/.yamllint b/{{cookiecutter.project_slug}}/.yamllint deleted file mode 100644 index 83f5340c..00000000 --- a/{{cookiecutter.project_slug}}/.yamllint +++ /dev/null @@ -1,29 +0,0 @@ ---- - -extends: default - -rules: - braces: - level: warning - max-spaces-inside: 1 - brackets: - level: warning - max-spaces-inside: 1 - colons: - level: warning - commas: - level: warning - comments: disable - comments-indentation: disable - document-start: disable - empty-lines: - level: warning - hyphens: - level: warning - indentation: - level: warning - indent-sequences: consistent - line-length: - level: warning - allow-non-breakable-inline-mappings: true - truthy: disable diff --git a/{{cookiecutter.project_slug}}/Makefile b/{{cookiecutter.project_slug}}/Makefile deleted file mode 100644 index 701c00bd..00000000 --- a/{{cookiecutter.project_slug}}/Makefile +++ /dev/null @@ -1,183 +0,0 @@ -KUBECTL_EXEC_BACKEND = kubectl exec -it $$(kubectl get pods -l app=backend -o jsonpath="{.items[0].metadata.name}") -- bash -{% if cookiecutter.create_nextjs_frontend == "y" %} -KUBECTL_EXEC_FRONTEND = kubectl exec -it $$(kubectl get pods -l app=frontend -o jsonpath="{.items[0].metadata.name}") -- bash -{% endif %} - -# colors -BLUE:=$(shell echo "\033[0;36m") -GREEN:=$(shell echo "\033[0;32m") -YELLOW:=$(shell echo "\033[0;33m") -RED:=$(shell echo "\033[0;31m") -END:=$(shell echo "\033[0m") - -PROJECT_SLUG:="{{ cookiecutter.project_slug }}" - -## Release/Deployment Targets - -ci: test secure build ## Execute the same checks used in CI/CD - -.git/hooks/pre-commit: ## Install pre-commit hooks - pip install pre-commit; \ - cd backend/; \ - pre-commit install - -check-lint-and-formatting: .git/hooks/pre-commit ## Execute check of lint and formatting using existing pre-commit hooks - cd backend; \ - pre-commit run -a - -{% if cookiecutter.create_nextjs_frontend == 'y' %} -check-lint-and-test-frontend: ## Frontend Lint & Typecheck & Test - cd frontend/; \ - npm install --legacy-peer-deps; \ - npm run lint-src; \ - npm run typecheck; \ - npm run test -{% endif %} - -backend-test: ## Execute backend tests -ifeq ($(CI),true) - pip install uv; \ - cd backend; \ - uv venv ./venv; \ - . ./venv/bin/activate; \ - uv pip install \ - -r requirements/production.txt \ - -r requirements/tests.txt; \ - cd scafman; \ - export DJANGO_SECRET_KEY="test"; \ - pytest --cov=./ --cov-report html --ds=config.settings.test -else - $(KUBECTL_EXEC_BACKEND) -c "cd {{ cookiecutter.project_slug }} && pytest --cov=./ --cov-report html --ds=config.settings.test" -endif - -{% if cookiecutter.create_nextjs_frontend == 'y' %} -frontend-test: ## Execute frontend tests -ifeq ($(CI),true) - cd frontend/; \ - npm ci; \ - npm run test -else - $(KUBECTL_EXEC_FRONTEND) -c "npm run test" -endif - -test: backend-test frontend-test ## Run all tests -{% else %} -test: backend-test ## Run all tests -{% endif %} - -## Development Targets - -backend/requirements/local.txt: compile -backend/requirements/production.txt: compile -backend/requirements/tests.txt: compile - -setup: - @echo " $(YELLOW)⛭$(END) Checking if the setup is correct and all prerequisites are installed..." - @MISSING=""; \ - for exec in $(PREREQUISITE_COMMANDS); do \ - if ! which $$exec > /dev/null 2>&1; then \ - MISSING="$$MISSING $$exec"; \ - fi; \ - done; \ - if [ -n "$$MISSING" ]; then \ - echo " $(RED)❌$(END)Missing executables:$$MISSING. These must be installed by you to continue"; \ - false; \ - else \ - echo " $(GREEN)✔️$(END) All prerequisites are installed."; \ - fi - @CURRENT_CONTEXT="$$(kubectl config current-context 2>&1)"; \ - if [ "$$CURRENT_CONTEXT" = "kind-$(PROJECT_SLUG)" ]; then \ - echo " $(GREEN)✔️$(END) The kubectl context is correctly set to kind-$(PROJECT_SLUG). Run 'tilt up' to start your cluster!"; \ - else \ - echo " $(YELLOW)⛭$(END) Current kubectl context is not 'kind-$(PROJECT_SLUG)'. Switching context now..."; \ - if [ -z "$$(kubectl config get-contexts -o name | grep -w 'kind-$(PROJECT_SLUG)$$')" ]; then \ - echo " $(YELLOW)⛭$(END) No context found for kind-$(PROJECT_SLUG). Creating one. Please wait, this may take a couple of minutes on a slower machine..."; \ - kind create cluster --name $(PROJECT_SLUG) 1>/dev/null 2>/tmp/scaf_error.log; \ - echo " $(GREEN)✔️$(END) kind-$(PROJECT_SLUG) cluster and context created."; \ - echo " $(BLUE)🗣️ Remember, you can safely run \"make setup\" any time to switch between Scaf projects.$(END)"; \ - fi; \ - kubectl config use-context kind-$(PROJECT_SLUG) 1>/dev/null 2>/tmp/scaf_error.log; \ - echo " $(GREEN)✔️$(END) Context switched to kind-$(PROJECT_SLUG). Run 'tilt up' to start your cluster! "; \ - fi - -outdated: ## Show all the outdated packages with their latest versions in the container - $(KUBECTL_EXEC_BACKEND) -c "pip list --outdated" - -pipdeptree: ## Show the dependencies of installed packages as a tree structure - $(KUBECTL_EXEC_BACKEND) -c "uv pip tree --no-cache" - -compile: backend/requirements/base.in backend/requirements/tests.in ## compile latest requirements to be built into the docker image - @docker run --rm -v $(shell pwd)/backend/requirements:/local python:3.12-slim /bin/bash -c \ - "apt-get update; apt-get install -y libpq-dev; \ - pip install uv; \ - touch /local/base.txt; touch /local/production.txt; touch /local/tests.txt; touch /local/local.txt; \ - uv pip compile --upgrade --generate-hashes --output-file /local/base.txt /local/base.in; \ - uv pip compile --upgrade --generate-hashes --output-file /local/production.txt /local/production.in; \ - uv pip compile --upgrade --generate-hashes --output-file /local/tests.txt /local/tests.in; \ - uv pip compile --upgrade --output-file /local/local.txt /local/local.in" - -shell-backend: ## Shell into the running Django container - $(KUBECTL_EXEC_BACKEND) - -{% if cookiecutter.create_nextjs_frontend == "y" %} -shell-frontend: - $(KUBECTL_EXEC_FRONTEND) -{% endif %} - -secure: ## Analyze dependencies for security issues - $(KUBECTL_EXEC_BACKEND) -c "safety check" - -DEBUG ?= false -secrets: - @$(call check_var,ENVIRONMENT) - @echo "Creating sealed secrets for $$(kubectl config current-context) cluster" - kubectl config get-contexts --no-headers | \ - grep {{ cookiecutter.project_dash }}-$(ENVIRONMENT) && kubectl config use-context admin@{{ cookiecutter.project_dash }}-$(ENVIRONMENT) - AWS_S3_ACCESS_KEY_ID=$$(tofu -chdir=./terraform/$(ENVIRONMENT) output -raw cnpg_user_access_key) \ - AWS_S3_SECRET_ACCESS_KEY=$$(tofu -chdir=./terraform/$(ENVIRONMENT) output -raw cnpg_user_secret_key) \ -{% if cookiecutter.mail_service == "Amazon SES" %} AWS_SES_ACCESS_KEY_ID=$$(tofu -chdir=./terraform/$(ENVIRONMENT) output -raw amazon_ses_user_key) \ - AWS_SES_SECRET_ACCESS_KEY=$$(tofu -chdir=./terraform/$(ENVIRONMENT) output -raw amazon_ses_user_secret_key) \{% endif %} - DJANGO_SECRET_KEY=$$(LC_CTYPE=C tr -dc A-Za-z0-9 </dev/urandom | head -c 32; echo) \ - ENVIRONMENT=$(ENVIRONMENT) \ - envsubst < k8s/templates/secrets.yaml.template | op inject | if [ "$(DEBUG)" = "true" ]; then cat; else kubeseal -n {{ cookiecutter.project_slug }}-$(ENVIRONMENT) --format yaml > k8s/$(ENVIRONMENT)/secrets.yaml; fi - -sandbox-secrets: ## Create sealed secrets for sandbox - $(MAKE) secrets ENVIRONMENT=sandbox - -debug-sandbox-secrets: ## Debug sandbox secrets - $(MAKE) secrets ENVIRONMENT=sandbox DEBUG=true - -staging-secrets: ## Create sealed secrets for sandbox - $(MAKE) secrets ENVIRONMENT=sandbox - -debug-staging-secrets: ## Debug sandbox secrets - $(MAKE) secrets ENVIRONMENT=sandbox DEBUG=true - -prod-secrets: ## Create sealed secrets for prod - $(MAKE) secrets ENVIRONMENT=prod - -debug-prod-secrets: ## Create sealed secrets for prod - $(MAKE) secrets ENVIRONMENT=prod DEBUG=true - -ensure-uv: - @which uv >/dev/null 2>&1 || { echo "Installing uv..."; curl -LsSf https://astral.sh/uv/install.sh | sh; } - -docs: ensure-uv ## Build the Docs - uvx --with mkdocs-material --with mkdocs-mermaid2-plugin mkdocs build - -serve-docs: ensure-uv ## Serve the Docs - uvx --with mkdocs-material --with mkdocs-mermaid2-plugin mkdocs serve -a localhost:8001 - -## Help - -help: ## Show the list of all the commands and their help text - @awk 'BEGIN { FS = ":.*##"; target="";printf "\nUsage:\n make \033[36m<target>\033[33m\n\nTargets:\033[0m\n" } \ - /^[a-zA-Z_-]+:.*?##/ { if(target=="")print ""; target=$$1; printf " \033[36m%-10s\033[0m %s\n\n", $$1, $$2 } \ - /^([a-zA-Z_-]+):/ {if(target=="")print "";match($$0, "(.*):"); target=substr($$0,RSTART,RLENGTH) } \ - /^\t## (.*)/ { match($$0, "[^\t#:\\\\]+"); txt=substr($$0,RSTART,RLENGTH);printf " \033[36m%-10s\033[0m", target; printf " %s\n", txt ; target=""} \ - /^## .*/ {match($$0, "## (.+)$$"); txt=substr($$0,4,RLENGTH);printf "\n\033[33m%s\033[0m\n", txt ; target=""} \ - ' $(MAKEFILE_LIST) - -.PHONY: help check-lint-and-formatting ci ensure-uv secure build build-dev outdated pipdeptree compile destroy-data load-dump clean clean-dev squeaky_clean update check-sandbox-release check-staging-release check-prod-release - -.DEFAULT_GOAL := help diff --git a/{{cookiecutter.project_slug}}/README.md b/{{cookiecutter.project_slug}}/README.md deleted file mode 100644 index d395fe2a..00000000 --- a/{{cookiecutter.project_slug}}/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# {{ cookiecutter.project_name }} - -## :information_source: About the {{ cookiecutter.project_name }} project - -* [:telescope: Project overview](/docs/project-overview.md) -* [:house: Architecture](/docs/architecture.md) -<!-- * [:hospital: ER Diagram](/docs/erdiagram.md) --> - -## :technologist: How to set up your local environment for development - -See [docs/development.md](/docs/development.md) - -## :package: How to deploy - -See [docs/deployment.md](/docs/deployment.md) - -## :shushing_face: How to manage passwords and sensitive values - -See [docs/secrets.md](/docs/secrets.md) - -## :bug: How to debug the application - -See [docs/debug.md](/docs/debug.md) - -## :test_tube: How to test the application - -See [docs/qa.md](/docs/qa.md) - -## :microscope: How to monitor the application - -See [docs/monitoring.md](/docs/monitoring.md) diff --git a/{{cookiecutter.project_slug}}/Tiltfile b/{{cookiecutter.project_slug}}/Tiltfile deleted file mode 100644 index ce7439f9..00000000 --- a/{{cookiecutter.project_slug}}/Tiltfile +++ /dev/null @@ -1,62 +0,0 @@ -print( - """ ------------------------------------------------------------------ -✨ Hello Tilt! This appears in the (Tiltfile) pane whenever Tilt - evaluates this file. ------------------------------------------------------------------ -""".strip() -) - -load("ext://syncback", "syncback") - -docker_build( - "backend", - context="backend", - build_args={"DEVEL": "yes", "TEST": "yes"}, - live_update=[ - sync("./backend/config", "/app/src/config"), - sync("./backend/{{ cookiecutter.project_slug }}", "/app/src/{{ cookiecutter.project_slug }}"), - ], -) - -{% if cookiecutter.create_nextjs_frontend == "y" %} -docker_build( - "frontend", - context="frontend", - live_update=[ - sync("./frontend", "/app"), - ], -) -{% endif %} - -k8s_yaml( - kustomize("./k8s/local/") -) - -syncback( - "backend-sync", - "deploy/backend", - "/app/src/{{ cookiecutter.project_slug }}/", - target_dir="./backend/{{ cookiecutter.project_slug }}", - rsync_path='/app/bin/rsync.tilt', -) - -{% if cookiecutter.create_nextjs_frontend == "y" %} -syncback( - "frontend-sync", - "deploy/frontend", - "/app/", - target_dir="./frontend", - rsync_path='/app/rsync.tilt', -) -{% endif %} - -{% if cookiecutter.create_nextjs_frontend == "y" %} -k8s_resource(workload='frontend', port_forwards=3000) -{% endif %} -k8s_resource(workload='backend', port_forwards=8000) -k8s_resource(workload='mailhog', port_forwards=8025) -k8s_resource(workload='postgres', port_forwards=5432) -{% if cookiecutter.use_celery == 'y' %} -k8s_resource(workload='flower', port_forwards=5555) -{% endif %} \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/argocd/base/argocd/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/argocd/app.yaml deleted file mode 100644 index 1beedf5b..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/argocd/app.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: argocd - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: default - source: - chart: argo-cd - repoURL: https://argoproj.github.io/argo-helm - targetRevision: 6.9.2 - helm: - releaseName: argocd - # https://argo-cd.readthedocs.io/en/stable/operator-manual/ingress/#traefik-v22 - valuesObject: - configs: - params: - server.insecure: true - destination: - server: "https://kubernetes.default.svc" - namespace: argocd - syncPolicy: - automated: - prune: true - selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m diff --git a/{{cookiecutter.project_slug}}/argocd/base/argocd/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/argocd/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/argocd/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/base/cert-manager/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/cert-manager/app.yaml deleted file mode 100644 index 78d17cfd..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/cert-manager/app.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: cert-manager - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: default - source: - chart: cert-manager - repoURL: https://charts.jetstack.io - targetRevision: v1.14.5 - helm: - releaseName: cert-manager - parameters: - - name: "installCRDs" - value: "true" - destination: - server: "https://kubernetes.default.svc" - namespace: cert-manager - syncPolicy: - automated: - prune: true - selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m - syncOptions: - - CreateNamespace=true diff --git a/{{cookiecutter.project_slug}}/argocd/base/cert-manager/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/cert-manager/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/cert-manager/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/base/cloudnative-pg/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/cloudnative-pg/app.yaml deleted file mode 100644 index 842db5bc..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/cloudnative-pg/app.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: cloudnative-pg - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: default - source: - chart: cloudnative-pg - repoURL: https://cloudnative-pg.github.io/charts - targetRevision: v0.19.1 - helm: - releaseName: cloudnative-pg - parameters: - - name: "fullnameOverride" - value: "cnpg-controller-manager" - destination: - server: "https://kubernetes.default.svc" - namespace: cnpg-system - syncPolicy: - automated: - prune: true - selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m - syncOptions: - - CreateNamespace=true diff --git a/{{cookiecutter.project_slug}}/argocd/base/cloudnative-pg/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/cloudnative-pg/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/cloudnative-pg/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/base/ingress/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/ingress/app.yaml deleted file mode 100644 index 8149f052..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/ingress/app.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: ingress - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "3" -spec: - project: default - source: - repoURL: {{ cookiecutter.repo_url }} - targetRevision: main - path: argocd/prod/ingress - destination: - server: https://kubernetes.default.svc - namespace: default - syncPolicy: - automated: - prune: true - selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m - syncOptions: - - CreateNamespace=true diff --git a/{{cookiecutter.project_slug}}/argocd/base/ingress/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/ingress/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/ingress/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/base/kube-prometheus-stack/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/kube-prometheus-stack/app.yaml deleted file mode 100644 index dfb4e3da..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/kube-prometheus-stack/app.yaml +++ /dev/null @@ -1,62 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: kube-prometheus-stack - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - project: default - source: - chart: kube-prometheus-stack - repoURL: https://prometheus-community.github.io/helm-charts - targetRevision: 60.3.0 - helm: - releaseName: kube-prometheus-stack - valuesObject: - alertmanager: - enabled: false - grafana: - enabled: false - prometheusOperator: - resources: - limits: - cpu: 100m - memory: 200Mi - requests: - cpu: 50m - memory: 100Mi - prometheus: - prometheusSpec: - podMonitorSelectorNilUsesHelmValues: false - podMonitorSelector: {} - # Add retention configuration for Prometheus - retention: 90d - retentionSize: 9GB - # Adjust storage size if needed - storageSpec: - volumeClaimTemplate: - spec: - storageClassName: local-path - accessModes: ["ReadWriteOnce"] - resources: - requests: - storage: 10Gi - - destination: - server: "https://kubernetes.default.svc" - namespace: monitoring - syncPolicy: - automated: {} - # automated: - # prune: true - # selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m - syncOptions: - - CreateNamespace=true - - ServerSideApply=true diff --git a/{{cookiecutter.project_slug}}/argocd/base/kube-prometheus-stack/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/kube-prometheus-stack/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/kube-prometheus-stack/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/base/local-path-provisioner/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/local-path-provisioner/kustomization.yaml deleted file mode 100644 index 5bddcd33..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/local-path-provisioner/kustomization.yaml +++ /dev/null @@ -1,36 +0,0 @@ -# kustomization.yaml -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: -- github.com/rancher/local-path-provisioner/deploy?ref=v0.0.26 -patches: -- patch: |- - kind: ConfigMap - apiVersion: v1 - metadata: - name: local-path-config - namespace: local-path-storage - data: - config.json: |- - { - "nodePathMap":[ - { - "node":"DEFAULT_PATH_FOR_NON_LISTED_NODES", - "paths":["/var/local-path-provisioner"] - } - ] - } -- patch: |- - apiVersion: storage.k8s.io/v1 - kind: StorageClass - metadata: - name: local-path - annotations: - storageclass.kubernetes.io/is-default-class: "true" -- patch: |- - apiVersion: v1 - kind: Namespace - metadata: - name: local-path-storage - labels: - pod-security.kubernetes.io/enforce: privileged diff --git a/{{cookiecutter.project_slug}}/argocd/base/reflector/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/reflector/app.yaml deleted file mode 100644 index 7fc3d814..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/reflector/app.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: reflector - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: default - source: - chart: reflector - repoURL: https://emberstack.github.io/helm-charts - targetRevision: 7.1.262 - helm: - releaseName: reflector - destination: - server: "https://kubernetes.default.svc" - namespace: kube-system - syncPolicy: - automated: - prune: true - selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m diff --git a/{{cookiecutter.project_slug}}/argocd/base/reflector/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/reflector/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/reflector/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/base/sealed-secrets/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/sealed-secrets/app.yaml deleted file mode 100644 index 54ed77cc..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/sealed-secrets/app.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: sealed-secrets - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: default - source: - chart: sealed-secrets - repoURL: https://bitnami-labs.github.io/sealed-secrets - targetRevision: 2.13.2 - helm: - releaseName: sealed-secrets - parameters: - - name: "fullnameOverride" - value: sealed-secrets-controller - destination: - server: "https://kubernetes.default.svc" - namespace: kube-system - syncPolicy: - automated: - prune: true - selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m diff --git a/{{cookiecutter.project_slug}}/argocd/base/sealed-secrets/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/sealed-secrets/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/sealed-secrets/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/base/traefik/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/traefik/app.yaml deleted file mode 100644 index 9eb6ab8a..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/traefik/app.yaml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: traefik - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "0" -spec: - project: default - source: - chart: traefik - repoURL: https://traefik.github.io/charts - targetRevision: 28.0.0 - helm: - releaseName: traefik - parameters: - - name: "service.type" - value: NodePort - - name: "ports.web.nodePort" - value: "30080" - - name: "ports.websecure.nodePort" - value: "30443" - - name: "deployment.kind" - value: DaemonSet - destination: - server: "https://kubernetes.default.svc" - namespace: kube-system - syncPolicy: - automated: - prune: true - selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m diff --git a/{{cookiecutter.project_slug}}/argocd/base/traefik/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/traefik/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/traefik/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/base/{{ cookiecutter.project_slug }}/app.yaml b/{{cookiecutter.project_slug}}/argocd/base/{{ cookiecutter.project_slug }}/app.yaml deleted file mode 100644 index 96e4f4dc..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/{{ cookiecutter.project_slug }}/app.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: {{ cookiecutter.project_slug }}-prod - namespace: argocd -spec: - project: default - source: - repoURL: {{ cookiecutter.repo_url }} - targetRevision: main - path: k8s/prod - destination: - server: https://kubernetes.default.svc - namespace: {{ cookiecutter.project_slug }}-prod - syncPolicy: - automated: - prune: true - selfHeal: true - retry: - limit: 5 - backoff: - duration: 5s - factor: 2 - maxDuration: 3m - syncOptions: - - CreateNamespace=true diff --git a/{{cookiecutter.project_slug}}/argocd/base/{{ cookiecutter.project_slug }}/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/base/{{ cookiecutter.project_slug }}/kustomization.yaml deleted file mode 100644 index 98860a01..00000000 --- a/{{cookiecutter.project_slug}}/argocd/base/{{ cookiecutter.project_slug }}/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- app.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/prod/apps/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/prod/apps/kustomization.yaml deleted file mode 100644 index fdeb2bd7..00000000 --- a/{{cookiecutter.project_slug}}/argocd/prod/apps/kustomization.yaml +++ /dev/null @@ -1,25 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- ../../base/argocd -- ../../base/cert-manager -- ../../base/cloudnative-pg -- ../../base/ingress -- ../../base/kube-prometheus-stack -- ../../base/local-path-provisioner -- ../../base/reflector -- ../../base/sealed-secrets -- ../../base/traefik -- ../../base/{{ cookiecutter.project_slug }} -kind: Kustomization -patches: -- patch: |- - - op: replace - path: /spec/source/targetRevision - value: main - - op: replace - path: /spec/source/path - value: argocd/prod/ingress - target: - kind: Application - name: ingress diff --git a/{{cookiecutter.project_slug}}/argocd/prod/ingress/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/prod/ingress/kustomization.yaml deleted file mode 100644 index c16b76dc..00000000 --- a/{{cookiecutter.project_slug}}/argocd/prod/ingress/kustomization.yaml +++ /dev/null @@ -1,35 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -resources: -- ../../sandbox/ingress -patches: -- patch: |- - - op: replace - path: /metadata/name - value: argocd-{{ cookiecutter.project_slug }}-tls - - op: replace - path: /spec/secretName - value: argocd-{{ cookiecutter.project_slug }}-tls - - op: replace - path: /spec/dnsNames - value: - - argocd.{{ cookiecutter.domain_name }} - target: - kind: Certificate - name: argocd-sandbox-{{ cookiecutter.project_slug }}-tls -- patch: |- - - op: replace - path: /metadata/name - value: argocd-{{ cookiecutter.project_slug }} - - op: replace - path: /spec/routes/0/match - value: Host(`argocd.{{ cookiecutter.domain_name }}`) - - op: replace - path: /spec/routes/1/match - value: Host(`argocd.{{ cookiecutter.domain_name }}`) && Headers(`Content-Type`, `application/grpc`) - - op: replace - path: /spec/tls - value: argocd-{{ cookiecutter.project_slug }}-tls - target: - kind: IngressRoute - name: argocd-sandbox-{{ cookiecutter.project_slug }} -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/argocd/sandbox/apps/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/sandbox/apps/kustomization.yaml deleted file mode 100644 index 96f0a07e..00000000 --- a/{{cookiecutter.project_slug}}/argocd/sandbox/apps/kustomization.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -namespace: argocd -resources: -- ../../base/argocd -- ../../base/cert-manager -- ../../base/cloudnative-pg -- ../../base/ingress -- ../../base/local-path-provisioner -- ../../base/reflector -- ../../base/sealed-secrets -- ../../base/traefik -- ../../base/{{ cookiecutter.project_slug }} -kind: Kustomization -patches: -- patch: |- - - op: replace - path: /spec/source/targetRevision - value: develop - - op: replace - path: /spec/source/path - value: argocd/sandbox/ingress - target: - kind: Application - name: ingress -- patch: |- - - op: replace - path: /spec/source/targetRevision - value: develop - - op: replace - path: /metadata/name - value: {{ cookiecutter.project_slug }}-sandbox - - op: replace - path: /spec/source/path - value: k8s/sandbox - - op: replace - path: /spec/destination/namespace - value: {{ cookiecutter.project_slug }}-sandbox - target: - kind: Application - name: {{ cookiecutter.project_slug }}-prod diff --git a/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/cert-manager-issuer.yaml b/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/cert-manager-issuer.yaml deleted file mode 100644 index f3b58484..00000000 --- a/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/cert-manager-issuer.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: letsencrypt-prod - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - acme: - server: https://acme-v02.api.letsencrypt.org/directory - email: {{ cookiecutter.email }} - privateKeySecretRef: - name: letsencrypt-prod - solvers: - - http01: - ingress: - class: traefik ---- -apiVersion: cert-manager.io/v1 -kind: ClusterIssuer -metadata: - name: letsencrypt-staging - annotations: - argocd.argoproj.io/sync-wave: "1" -spec: - acme: - server: https://acme-staging-v02.api.letsencrypt.org/directory - email: {{ cookiecutter.email }} - privateKeySecretRef: - name: letsencrypt-staging - solvers: - - http01: - ingress: - class: traefik diff --git a/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/certificates.yaml b/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/certificates.yaml deleted file mode 100644 index 01107ada..00000000 --- a/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/certificates.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: argocd-sandbox-{{ cookiecutter.project_slug }}-tls - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "3" -spec: - secretName: argocd-sandbox-{{ cookiecutter.project_slug }}-tls - issuerRef: - name: letsencrypt-prod - kind: ClusterIssuer - dnsNames: - - argocd.sandbox.{{ cookiecutter.domain_name }} diff --git a/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/ingress.yaml b/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/ingress.yaml deleted file mode 100644 index f7711494..00000000 --- a/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/ingress.yaml +++ /dev/null @@ -1,59 +0,0 @@ ---- -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: argocd-sandbox-{{ cookiecutter.project_slug }} - annotations: - argocd.argoproj.io/sync-wave: "2" - namespace: argocd -spec: - entryPoints: - - websecure - routes: - - kind: Rule - match: Host(`argocd.sandbox.{{ cookiecutter.domain_name }}`) - priority: 10 - services: - - name: argocd-server - port: 80 - - kind: Rule - match: Host(`argocd.sandbox.{{ cookiecutter.domain_name }}`) && Headers(`Content-Type`, `application/grpc`) - priority: 11 - services: - - name: argocd-server - port: 80 - scheme: h2c - tls: - secretName: argocd-sandbox-{{ cookiecutter.project_slug }}-tls ---- -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: http-to-https-redirect - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "5" -spec: - entryPoints: - - web - routes: - - kind: Rule - match: PathPrefix(`/`) - priority: 1 - middlewares: - - name: redirect-to-https - services: - - kind: TraefikService - name: noop@internal ---- -apiVersion: traefik.io/v1alpha1 -kind: Middleware -metadata: - name: redirect-to-https - namespace: argocd - annotations: - argocd.argoproj.io/sync-wave: "5" -spec: - redirectScheme: - scheme: https - permanent: true diff --git a/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/kustomization.yaml b/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/kustomization.yaml deleted file mode 100644 index f8369620..00000000 --- a/{{cookiecutter.project_slug}}/argocd/sandbox/ingress/kustomization.yaml +++ /dev/null @@ -1,6 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -resources: -- cert-manager-issuer.yaml -- certificates.yaml -- ingress.yaml -kind: Kustomization diff --git a/{{cookiecutter.project_slug}}/backend/Dockerfile b/{{cookiecutter.project_slug}}/backend/Dockerfile deleted file mode 100644 index c3715082..00000000 --- a/{{cookiecutter.project_slug}}/backend/Dockerfile +++ /dev/null @@ -1,106 +0,0 @@ -# Build all of the dependencies then we will build the actual application image -FROM python:3.12-slim as build - -ENV PYTHONUNBUFFERED 1 -ENV PYTHONDONTWRITEBYTECODE 1 -ENV BOGUS 1 - -ARG DEVEL=no -ARG TEST=no - -RUN apt-get update \ - && apt-get install --no-install-recommends -y \ - build-essential \ - ca-certificates \ - curl \ - gettext \ - gnupg \ - && curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ - && echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ - && apt-get update \ - && apt-get install --no-install-recommends -y \ - libffi-dev \ - libpq-dev \ - libssl-dev \ - postgresql-client-16 \ - postgresql-client-common - - -# We create an /app directory with a virtual environment in it to store our -# application in. -RUN set -x \ - && python3 -m venv /app - -# Now that we've created our virtual environment, we'll go ahead and update -# our $PATH to refer to it first. -ENV PATH="/app/bin:${PATH}" - -# Next, we want to update pip, setuptools, and wheel inside of this virtual -# environment to ensure that we have the latest versions of them. -RUN pip --no-cache-dir install --upgrade uv -RUN uv pip --no-cache install --upgrade setuptools wheel - -COPY requirements /tmp/requirements - -RUN set -x \ - && if [ "$DEVEL" = "yes" ]; then uv pip --no-cache install -r /tmp/requirements/local.txt; fi - -RUN set -x \ - && uv pip --no-cache install --no-deps \ - -r /tmp/requirements/production.txt \ - -r /tmp/requirements/base.txt - -RUN set -x \ - && if [ "$TEST" = "yes" ]; then uv pip --no-cache install --no-deps \ - -r /tmp/requirements/tests.txt; fi - -# Now we can build the application image -FROM python:3.12-slim - -ENV PYTHONUNBUFFERED 1 -ENV PYTHONPATH /app -ENV PATH="/app/bin:${PATH}" -ENV BOGUS 1 - -WORKDIR /app/src - -ARG DEVEL=no -# this is used by Sentry to associate errors with releases -ARG RELEASE="dev" - -# This is a work around because otherwise postgresql-client bombs out trying -# to create symlinks to these directories. -RUN set -x \ - && mkdir -p /usr/share/man/man1 \ - && mkdir -p /usr/share/man/man7 - -RUN apt-get update \ - # psycopg2 dependencies - && apt-get install --no-install-recommends -y \ - ca-certificates \ - curl \ - gettext \ - gnupg \ - && curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ - && echo "deb http://apt.postgresql.org/pub/repos/apt bookworm-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ - && apt-get update \ - && apt-get install --no-install-recommends -y \ - libpq5 \ - $(if [ "$DEVEL" = "yes" ]; then echo 'bash postgresql-client-16'; fi) \ - # awscli - && apt-get install -y \ - awscli \ - # cleaning up unused files - && apt-get remove -y \ - curl \ - gnupg \ - && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \ - && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -RUN adduser --system --no-create-home django -COPY --chown=django:django --from=build /app/ /app/ -COPY --chown=django:django config/ /app/src/config/ -COPY --chown=django:django manage.py /app/src/ -COPY --chown=django:django {{ cookiecutter.project_slug }}/ /app/src/{{ cookiecutter.project_slug }}/ - -USER django diff --git a/{{cookiecutter.project_slug}}/backend/config/__init__.py b/{{cookiecutter.project_slug}}/backend/config/__init__.py deleted file mode 100644 index 2fa88e31..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -{% if cookiecutter.use_celery == 'y' -%} -# This will make sure the app is always imported when -# Django starts so that shared_task will use this app. -from {{ cookiecutter.project_slug }}.celery import app as celery_app - -__all__ = ("celery_app",) -{% endif -%} diff --git a/{{cookiecutter.project_slug}}/backend/config/asgi.py b/{{cookiecutter.project_slug}}/backend/config/asgi.py deleted file mode 100644 index 6305b96d..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/asgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -ASGI config for {{ cookiecutter.project_name }} project. - -It exposes the ASGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/dev/howto/deployment/asgi/ - -""" -import os - -from django.core.asgi import get_asgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") - -application = get_asgi_application() diff --git a/{{cookiecutter.project_slug}}/backend/config/schema.py b/{{cookiecutter.project_slug}}/backend/config/schema.py deleted file mode 100644 index 21bc5567..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/schema.py +++ /dev/null @@ -1,11 +0,0 @@ -import strawberry -from strawberry_django.optimizer import DjangoOptimizerExtension - -from {{ cookiecutter.project_slug }}.users.queries import UserQuery -from {{ cookiecutter.project_slug }}.users.mutations import UserMutation - - -schema = strawberry.Schema(query=UserQuery, mutation=UserMutation, extensions=[ - # other extensions... - DjangoOptimizerExtension, -]) diff --git a/{{cookiecutter.project_slug}}/backend/config/settings/__init__.py b/{{cookiecutter.project_slug}}/backend/config/settings/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/{{cookiecutter.project_slug}}/backend/config/settings/base.py b/{{cookiecutter.project_slug}}/backend/config/settings/base.py deleted file mode 100644 index 377015da..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/settings/base.py +++ /dev/null @@ -1,347 +0,0 @@ -""" -Base settings to build other settings files upon. -""" -from pathlib import Path - -import environ - -{% if cookiecutter.use_sentry == 'y' %} -import sentry_sdk - -{% endif %} - -ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent -# {{ cookiecutter.project_slug }}/ -APPS_DIR = ROOT_DIR / "{{ cookiecutter.project_slug }}" -env = environ.Env() - -READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=False) -if READ_DOT_ENV_FILE: - # OS environment variables take precedence over variables from .env - env.read_env(str(ROOT_DIR / ".env")) - -# GENERAL -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#debug -DEBUG = env.bool("DJANGO_DEBUG", False) -# Local time zone. Choices are -# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name -# though not all of them may be available with every OS. -# In Windows, this must be set to your system time zone. -TIME_ZONE = "{{ cookiecutter.timezone }}" -# https://docs.djangoproject.com/en/dev/ref/settings/#language-code -LANGUAGE_CODE = "en-us" -# https://docs.djangoproject.com/en/dev/ref/settings/#site-id -SITE_ID = 1 -# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n -USE_I18N = True -# https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n -USE_L10N = True -# https://docs.djangoproject.com/en/dev/ref/settings/#use-tz -USE_TZ = True -# https://docs.djangoproject.com/en/dev/ref/settings/#locale-paths -LOCALE_PATHS = [str(ROOT_DIR / "locale")] - -# DATABASES -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#databases -DATABASES = {"default": env.db("DATABASE_URL")} -DATABASES["default"]["ATOMIC_REQUESTS"] = True - -# URLS -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf -ROOT_URLCONF = "config.urls" -# https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application -WSGI_APPLICATION = "config.wsgi.application" -ASGI_APPLICATION = "config.asgi.application" - -# APPS -# ------------------------------------------------------------------------------ -DJANGO_APPS = [ - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.sites", - "django.contrib.messages", - "django.contrib.staticfiles", - # "django.contrib.humanize", # Handy template tags - "django.contrib.admin", - "django.forms", -] -THIRD_PARTY_APPS = [ - "crispy_forms", - "crispy_bootstrap5", - "allauth", - "allauth.account", - "allauth.socialaccount", -{%- if cookiecutter.use_celery == "y" %} - "django_celery_beat", -{%- endif %} -{%- if cookiecutter.create_nextjs_frontend == "y" %} - "strawberry_django", - "corsheaders", -{%- endif %} -] - -LOCAL_APPS = [ - "{{ cookiecutter.project_slug }}.users.apps.UsersConfig", - {% if cookiecutter._challenge == "y" -%} - "{{ cookiecutter.project_slug }}.challenge.apps.ChallengeConfig", - {%- endif %} - # Your stuff: custom apps go here -] -# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps -INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS - -# MIGRATIONS -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules -MIGRATION_MODULES = {"sites": "{{ cookiecutter.project_slug }}.contrib.sites.migrations"} - -# AUTHENTICATION -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends -AUTHENTICATION_BACKENDS = [ - "django.contrib.auth.backends.ModelBackend", - "allauth.account.auth_backends.AuthenticationBackend", -] -# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model -AUTH_USER_MODEL = "users.User" -# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url -LOGIN_REDIRECT_URL = "users:redirect" -# https://docs.djangoproject.com/en/dev/ref/settings/#login-url -LOGIN_URL = "account_login" - -# PASSWORDS -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers -PASSWORD_HASHERS = [ - # https://docs.djangoproject.com/en/dev/topics/auth/passwords/#using-argon2-with-django - "django.contrib.auth.hashers.Argon2PasswordHasher", - "django.contrib.auth.hashers.PBKDF2PasswordHasher", - "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", - "django.contrib.auth.hashers.BCryptSHA256PasswordHasher", -] -# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators -AUTH_PASSWORD_VALIDATORS = [ - { - "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator" - }, - {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"}, - {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"}, - {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"}, -] - -# MIDDLEWARE -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#middleware -MIDDLEWARE = [ - "allauth.account.middleware.AccountMiddleware", - "django.middleware.security.SecurityMiddleware", - "django.contrib.sessions.middleware.SessionMiddleware", - "{{ cookiecutter.project_slug }}.utils.healthcheck.HealthCheckMiddleware", - "django.middleware.locale.LocaleMiddleware", - {%- if cookiecutter.create_nextjs_frontend == "y" %} - "corsheaders.middleware.CorsMiddleware", - {%- endif %} - "django.middleware.common.CommonMiddleware", - "django.middleware.csrf.CsrfViewMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", - "django.contrib.messages.middleware.MessageMiddleware", - "django.middleware.common.BrokenLinkEmailsMiddleware", - "django.middleware.clickjacking.XFrameOptionsMiddleware", -] - -# STATIC -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#static-root -STATIC_ROOT = str(ROOT_DIR / "staticfiles") -# https://docs.djangoproject.com/en/dev/ref/settings/#static-url -STATIC_URL = "/static/" -# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS -STATICFILES_DIRS = [str(APPS_DIR / "static")] -# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders -STATICFILES_FINDERS = [ - "django.contrib.staticfiles.finders.FileSystemFinder", - "django.contrib.staticfiles.finders.AppDirectoriesFinder", -] - -# MEDIA -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#media-root -MEDIA_ROOT = str(APPS_DIR / "media") -# https://docs.djangoproject.com/en/dev/ref/settings/#media-url -MEDIA_URL = "/media/" - -# TEMPLATES -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#templates -TEMPLATES = [ - { - # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND - "BACKEND": "django.template.backends.django.DjangoTemplates", - # https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs - "DIRS": [str(APPS_DIR / "templates")], - "OPTIONS": { - # https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders - # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types - "loaders": [ - "django.template.loaders.filesystem.Loader", - "django.template.loaders.app_directories.Loader", - ], - # https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors - "context_processors": [ - "django.template.context_processors.debug", - "django.template.context_processors.request", - "django.contrib.auth.context_processors.auth", - "django.template.context_processors.i18n", - "django.template.context_processors.media", - "django.template.context_processors.static", - "django.template.context_processors.tz", - "django.contrib.messages.context_processors.messages", - "{{ cookiecutter.project_slug }}.utils.context_processors.settings_context", - ], - }, - } -] - -# https://docs.djangoproject.com/en/dev/ref/settings/#form-renderer -FORM_RENDERER = "django.forms.renderers.TemplatesSetting" - -# http://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs -CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" - -CRISPY_TEMPLATE_PACK = "bootstrap5" - -# FIXTURES -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs -FIXTURE_DIRS = (str(APPS_DIR / "fixtures"),) - -# SECURITY -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-httponly -SESSION_COOKIE_HTTPONLY = True -# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-httponly -CSRF_COOKIE_HTTPONLY = True -# https://docs.djangoproject.com/en/dev/ref/settings/#secure-browser-xss-filter -SECURE_BROWSER_XSS_FILTER = True -# https://docs.djangoproject.com/en/dev/ref/settings/#x-frame-options -X_FRAME_OPTIONS = "DENY" - -# EMAIL -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend -EMAIL_BACKEND = env( - "DJANGO_EMAIL_BACKEND", default="django.core.mail.backends.smtp.EmailBackend" -) -# https://docs.djangoproject.com/en/dev/ref/settings/#email-timeout -EMAIL_TIMEOUT = 5 - -# ADMIN -# ------------------------------------------------------------------------------ -# Django Admin URL. -ADMIN_URL = "admin/" -# https://docs.djangoproject.com/en/dev/ref/settings/#admins -ADMINS = [("""{{ cookiecutter.author_name }}""", "{{ cookiecutter.email }}")] -# https://docs.djangoproject.com/en/dev/ref/settings/#managers -MANAGERS = ADMINS - -# LOGGING -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#logging -# See https://docs.djangoproject.com/en/dev/topics/logging for -# more details on how to customize your logging configuration. -LOGGING = { - "version": 1, - "disable_existing_loggers": False, - "formatters": { - "verbose": { - "format": "%(levelname)s %(asctime)s %(module)s " - "%(process)d %(thread)d %(message)s" - } - }, - "handlers": { - "console": { - "level": "DEBUG", - "class": "logging.StreamHandler", - "formatter": "verbose", - } - }, - "root": {"level": "INFO", "handlers": ["console"]}, -} - -{% if cookiecutter.use_celery == "y" -%} -# Celery -# ------------------------------------------------------------------------------ -if USE_TZ: - # http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-timezone - CELERY_TIMEZONE = TIME_ZONE -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-broker_url -CELERY_BROKER_URL = env("CELERY_BROKER_URL") -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-result_backend -CELERY_RESULT_BACKEND = CELERY_BROKER_URL -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-accept_content -CELERY_ACCEPT_CONTENT = ["json"] -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-task_serializer -CELERY_TASK_SERIALIZER = "json" -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#std:setting-result_serializer -CELERY_RESULT_SERIALIZER = "json" -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-time-limit -# TODO: set to whatever value is adequate in your circumstances -CELERY_TASK_TIME_LIMIT = 5 * 60 -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-soft-time-limit -# TODO: set to whatever value is adequate in your circumstances -CELERY_TASK_SOFT_TIME_LIMIT = 60 -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#beat-scheduler -CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers:DatabaseScheduler" - -{%- endif %} -# django-allauth -# ------------------------------------------------------------------------------ -ACCOUNT_ALLOW_REGISTRATION = env.bool("DJANGO_ACCOUNT_ALLOW_REGISTRATION", True) -# https://django-allauth.readthedocs.io/en/latest/configuration.html -ACCOUNT_AUTHENTICATION_METHOD = "username" -# https://django-allauth.readthedocs.io/en/latest/configuration.html -ACCOUNT_EMAIL_REQUIRED = True -# https://django-allauth.readthedocs.io/en/latest/configuration.html -ACCOUNT_EMAIL_VERIFICATION = "mandatory" -# https://django-allauth.readthedocs.io/en/latest/configuration.html -ACCOUNT_ADAPTER = "{{ cookiecutter.project_slug }}.users.adapters.AccountAdapter" -# https://django-allauth.readthedocs.io/en/latest/configuration.html -SOCIALACCOUNT_ADAPTER = "{{ cookiecutter.project_slug }}.users.adapters.SocialAccountAdapter" -DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" - -{% if cookiecutter.use_sentry == 'y' %} -# ------------------------------------------------------------------------------ -# Sentry -sentry_sdk.init( - dsn=env.str("SENTRY_DSN_BACKEND", default=""), - environment=env.str("ENVIRONMENT", default="production"), - release=env.str("RELEASE", default="dev"), -) -{% endif %} - -{%- if cookiecutter.create_nextjs_frontend == "y" %} -# ------------------------------------------------------------------------------ -# GraphQL settings -STRAWBERRY_DJANGO = { - "FIELD_DESCRIPTION_FROM_HELP_TEXT": True, - "TYPE_DESCRIPTION_FROM_MODEL_DOCSTRING": True, - "MUTATIONS_DEFAULT_ARGUMENT_NAME": "input", - "MUTATIONS_DEFAULT_HANDLE_ERRORS": True, -} -{%- endif %} - - -{%- if cookiecutter._challenge == "y" %} -# ------------------------------------------------------------------------------ -# CHALLENGE settings -CHALLENGE_SESSION_ID = env("CHALLENGE_SESSION_ID") -CHALLENGE_JWT_TOKEN = env("CHALLENGE_JWT_TOKEN") -CHALLENGE_BASE_URL = env("CHALLENGE_BASE_URL") -{%- endif %} - -# Your stuff... -# ------------------------------------------------------------------------------ diff --git a/{{cookiecutter.project_slug}}/backend/config/settings/local.py b/{{cookiecutter.project_slug}}/backend/config/settings/local.py deleted file mode 100644 index 759335a3..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/settings/local.py +++ /dev/null @@ -1,75 +0,0 @@ -from .base import * # noqa -from .base import env - -# GENERAL -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#debug -DEBUG = True -# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key -SECRET_KEY = env( - "DJANGO_SECRET_KEY" -), -# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts -ALLOWED_HOSTS = env( - "DJANGO_ALLOWED_HOSTS", - default=["backend", "localhost", "127.0.0.1"], -) - -# CACHES -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#caches -CACHES = { - "default": { - "BACKEND": "django.core.cache.backends.locmem.LocMemCache", - "LOCATION": "", - } -} - -# EMAIL -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#email-host -EMAIL_HOST = env("EMAIL_HOST", default="mailhog") -# https://docs.djangoproject.com/en/dev/ref/settings/#email-port -EMAIL_PORT = 1025 - -# django-debug-toolbar -# ------------------------------------------------------------------------------ -# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites -INSTALLED_APPS += ["debug_toolbar"] # noqa F405 -# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware -MIDDLEWARE += ["debug_toolbar.middleware.DebugToolbarMiddleware"] # noqa F405 -# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config -DEBUG_TOOLBAR_CONFIG = { - "DISABLE_PANELS": ["debug_toolbar.panels.redirects.RedirectsPanel"], - "SHOW_TEMPLATE_CONTEXT": True, -} -# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#internal-ips -INTERNAL_IPS = ["127.0.0.1", "10.0.2.2"] -if env("USE_DOCKER") == "yes": - import socket - - hostname, _, ips = socket.gethostbyname_ex(socket.gethostname()) - INTERNAL_IPS += [".".join(ip.split(".")[:-1] + ["1"]) for ip in ips] - -# django-extensions -# ------------------------------------------------------------------------------ -# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration -# INSTALLED_APPS += ["django_extensions"] # noqa F405 - -{% if cookiecutter.use_celery == 'y' -%} - -# Celery -# ------------------------------------------------------------------------------ -# http://docs.celeryproject.org/en/latest/userguide/configuration.html#task-eager-propagates -CELERY_TASK_EAGER_PROPAGATES = True - -{%- endif %} - -{%- if cookiecutter.create_nextjs_frontend == "y" %} -# ------------------------------------------------------------------------------ -# CORS settings -CORS_ALLOW_ALL_ORIGINS = True -CORS_ALLOW_CREDENTIALS = True -{%- endif %} -# Your stuff... -# ------------------------------------------------------------------------------ diff --git a/{{cookiecutter.project_slug}}/backend/config/settings/production.py b/{{cookiecutter.project_slug}}/backend/config/settings/production.py deleted file mode 100644 index e48b7d6e..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/settings/production.py +++ /dev/null @@ -1,192 +0,0 @@ -from .base import * # noqa -from .base import env - -# GENERAL -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key -SECRET_KEY = env("DJANGO_SECRET_KEY") -# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts -ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=["{{ cookiecutter.domain_name }}"]) -CSRF_TRUSTED_ORIGINS = env.list( - "DJANGO_CSRF_TRUSTED_ORIGINS", - default=["http://localhost", "https://{{ cookiecutter.domain_name }}"], -) -# DATABASES -# ------------------------------------------------------------------------------ -DATABASES["default"] = env.db("DATABASE_URL") # noqa F405 -DATABASES["default"]["ATOMIC_REQUESTS"] = True # noqa F405 -DATABASES["default"]["CONN_MAX_AGE"] = env.int("CONN_MAX_AGE", default=60) # noqa F405 - -# CACHES -# ------------------------------------------------------------------------------ -CACHES = { - "default": { - "BACKEND": "django_redis.cache.RedisCache", - "LOCATION": env("REDIS_URL"), - "OPTIONS": { - "CLIENT_CLASS": "django_redis.client.DefaultClient", - # Mimicing memcache behavior. - # http://jazzband.github.io/django-redis/latest/#_memcached_exceptions_behavior - "IGNORE_EXCEPTIONS": True, - }, - } -} - -# SECURITY -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header -SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") -# https://docs.djangoproject.com/en/dev/ref/settings/#secure-ssl-redirect -SECURE_SSL_REDIRECT = env.bool("DJANGO_SECURE_SSL_REDIRECT", default=True) -# https://docs.djangoproject.com/en/dev/ref/settings/#session-cookie-secure -SESSION_COOKIE_SECURE = True -# https://docs.djangoproject.com/en/dev/ref/settings/#csrf-cookie-secure -CSRF_COOKIE_SECURE = True -# https://docs.djangoproject.com/en/dev/topics/security/#ssl-https -# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-seconds -# TODO: set this to 60 seconds first and then to 518400 once you prove the former works -SECURE_HSTS_SECONDS = 60 -# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-include-subdomains -SECURE_HSTS_INCLUDE_SUBDOMAINS = env.bool( - "DJANGO_SECURE_HSTS_INCLUDE_SUBDOMAINS", default=True -) -# https://docs.djangoproject.com/en/dev/ref/settings/#secure-hsts-preload -SECURE_HSTS_PRELOAD = env.bool("DJANGO_SECURE_HSTS_PRELOAD", default=True) -# https://docs.djangoproject.com/en/dev/ref/middleware/#x-content-type-options-nosniff -SECURE_CONTENT_TYPE_NOSNIFF = env.bool( - "DJANGO_SECURE_CONTENT_TYPE_NOSNIFF", default=True -) - -# STORAGES -# ------------------------------------------------------------------------------ -# https://django-storages.readthedocs.io/en/latest/#installation -INSTALLED_APPS += ["storages"] # noqa F405 -# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings -AWS_STORAGE_BUCKET_NAME = env("DJANGO_AWS_STORAGE_BUCKET_NAME") -# It is required to set AWS_S3_CUSTOM_DOMAIN when the bucket is private and static content is served through CloudFront -AWS_S3_CUSTOM_DOMAIN = env("AWS_S3_CUSTOM_DOMAIN", default=None) -AWS_S3_URL_PROTOCOL = env("AWS_S3_CUSTOM_DOMAIN_PROTOCOL", default="https:") -# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings -AWS_QUERYSTRING_AUTH = False -# DO NOT change these unless you know what you're doing. -_AWS_EXPIRY = 60 * 60 * 24 * 7 -# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings -AWS_S3_OBJECT_PARAMETERS = { - "CacheControl": f"max-age={_AWS_EXPIRY}, s-maxage={_AWS_EXPIRY}, must-revalidate" -} -# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings -AWS_DEFAULT_ACL = "public-read" -# https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html#settings -AWS_S3_REGION_NAME = env("DJANGO_AWS_REGION_NAME", default="us-east-1") - -# STATIC -# ------------------------ -STATICFILES_STORAGE = "{{ cookiecutter.project_slug }}.utils.cloud_storage.S3StaticStorage" -STATIC_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/static/" - -# MEDIA -# ------------------------------------------------------------------------------ -DEFAULT_FILE_STORAGE = "{{ cookiecutter.project_slug }}.utils.cloud_storage.S3MediaStorage" -MEDIA_URL = f"https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/media/" - -# TEMPLATES -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#templates -TEMPLATES[-1]["OPTIONS"]["loaders"] = [ # type: ignore[index] # noqa F405 - ( - "django.template.loaders.cached.Loader", - [ - "django.template.loaders.filesystem.Loader", - "django.template.loaders.app_directories.Loader", - ], - ) -] - -# EMAIL -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#default-from-email -DEFAULT_FROM_EMAIL = env( - "DJANGO_DEFAULT_FROM_EMAIL", - default="{{ cookiecutter.project_name }} <noreply@{{ cookiecutter.domain_name }}>", -) -# https://docs.djangoproject.com/en/dev/ref/settings/#server-email -SERVER_EMAIL = env("DJANGO_SERVER_EMAIL", default=DEFAULT_FROM_EMAIL) -# https://docs.djangoproject.com/en/dev/ref/settings/#email-subject-prefix -EMAIL_SUBJECT_PREFIX = env( - "DJANGO_EMAIL_SUBJECT_PREFIX", - default="[{{ cookiecutter.project_name }}]", -) - -# ADMIN -# ------------------------------------------------------------------------------ -# Django Admin URL regex. -ADMIN_URL = env("DJANGO_ADMIN_URL") - -# Anymail -# ------------------------------------------------------------------------------ -# https://anymail.readthedocs.io/en/stable/installation/#installing-anymail -INSTALLED_APPS += ["anymail"] # noqa F405 -# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend -# https://anymail.readthedocs.io/en/stable/installation/#anymail-settings-reference -{%- if cookiecutter.mail_service == 'Mailgun' %} -# https://anymail.readthedocs.io/en/stable/esps/mailgun/ -EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend" -ANYMAIL = { - "MAILGUN_API_KEY": env("MAILGUN_API_KEY"), - "MAILGUN_SENDER_DOMAIN": env("MAILGUN_DOMAIN"), - "MAILGUN_API_URL": env("MAILGUN_API_URL", default="https://api.mailgun.net/v3"), -} -{%- elif cookiecutter.mail_service == 'Amazon SES' %} -# https://anymail.readthedocs.io/en/stable/esps/amazon_ses/ -EMAIL_BACKEND = "anymail.backends.amazon_ses.EmailBackend" -ANYMAIL = {} -{%- elif cookiecutter.mail_service == 'Other SMTP' %} -# https://anymail.readthedocs.io/en/stable/esps -EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" -ANYMAIL = {} -{%- endif %} - -# LOGGING -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#logging -# See https://docs.djangoproject.com/en/dev/topics/logging for -# more details on how to customize your logging configuration. -LOGGING = { - "version": 1, - "disable_existing_loggers": True, - "formatters": { - "verbose": { - "format": "%(levelname)s %(asctime)s %(module)s " - "%(process)d %(thread)d %(message)s" - } - }, - "handlers": { - "console": { - "level": "DEBUG", - "class": "logging.StreamHandler", - "formatter": "verbose", - } - }, - "root": {"level": "INFO", "handlers": ["console"]}, - "loggers": { - "django.db.backends": { - "level": "ERROR", - "handlers": ["console"], - "propagate": False, - }, - "django.security.DisallowedHost": { - "level": "ERROR", - "handlers": ["console"], - "propagate": False, - }, - }, -} - -{%- if cookiecutter.create_nextjs_frontend == "y" %} -# ------------------------------------------------------------------------------ -# CORS settings -CORS_ALLOWED_ORIGINS = env.list("CORS_ALLOWED_ORIGINS") -{%- endif %} - -# Your stuff... -# ------------------------------------------------------------------------------ diff --git a/{{cookiecutter.project_slug}}/backend/config/settings/test.py b/{{cookiecutter.project_slug}}/backend/config/settings/test.py deleted file mode 100644 index 1aa25e56..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/settings/test.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -With these settings, tests run faster. -""" - -from .base import * # noqa -from .base import env - -# GENERAL -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key -SECRET_KEY = env("DJANGO_SECRET_KEY") -# https://docs.djangoproject.com/en/dev/ref/settings/#test-runner -TEST_RUNNER = "django.test.runner.DiscoverRunner" - -# CACHES -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#caches -CACHES = { - "default": { - "BACKEND": "django.core.cache.backends.locmem.LocMemCache", - "LOCATION": "", - } -} - -# PASSWORDS -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#password-hashers -PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"] - -# TEMPLATES -# ------------------------------------------------------------------------------ -TEMPLATES[-1]["OPTIONS"]["loaders"] = [ # type: ignore[index] # noqa F405 - ( - "django.template.loaders.cached.Loader", - [ - "django.template.loaders.filesystem.Loader", - "django.template.loaders.app_directories.Loader", - ], - ) -] - -# EMAIL -# ------------------------------------------------------------------------------ -# https://docs.djangoproject.com/en/dev/ref/settings/#email-backend -EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend" - -# Your stuff... -# ------------------------------------------------------------------------------ diff --git a/{{cookiecutter.project_slug}}/backend/config/urls.py b/{{cookiecutter.project_slug}}/backend/config/urls.py deleted file mode 100644 index 24e3a549..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/urls.py +++ /dev/null @@ -1,59 +0,0 @@ -from django.conf import settings -from django.conf.urls.static import static -from django.contrib import admin -from django.contrib.staticfiles.urls import staticfiles_urlpatterns -from django.urls import include, path -from django.views import defaults as default_views -from django.views.generic import TemplateView -{%- if cookiecutter.create_nextjs_frontend == "y" %} -from strawberry.django.views import GraphQLView -from .schema import schema -{%- endif %} - -urlpatterns = [ - path("", TemplateView.as_view(template_name="pages/home.html"), name="home"), - path( - "about/", TemplateView.as_view(template_name="pages/about.html"), name="about" - ), - # Django Admin, use {% raw %}{% url 'admin:index' %}{% endraw %} - path(settings.ADMIN_URL, admin.site.urls), - # User management - path("users/", include("{{ cookiecutter.project_slug }}.users.urls", namespace="users")), - path("accounts/", include("allauth.urls")), - # Your stuff: custom urls includes go here -] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -if settings.DEBUG: - # Static file serving when using Gunicorn + Uvicorn for local web socket development - urlpatterns += staticfiles_urlpatterns() - -{%- if cookiecutter.create_nextjs_frontend == "y" %} -urlpatterns += [ - path("graphql/", GraphQLView.as_view(schema=schema)), -] -{%- endif %} - -if settings.DEBUG: - # This allows the error pages to be debugged during development, just visit - # these url in browser to see how these error pages look like. - urlpatterns += [ - path( - "400/", - default_views.bad_request, - kwargs={"exception": Exception("Bad Request!")}, - ), - path( - "403/", - default_views.permission_denied, - kwargs={"exception": Exception("Permission Denied")}, - ), - path( - "404/", - default_views.page_not_found, - kwargs={"exception": Exception("Page not Found")}, - ), - path("500/", default_views.server_error), - ] - if "debug_toolbar" in settings.INSTALLED_APPS: - import debug_toolbar - - urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns diff --git a/{{cookiecutter.project_slug}}/backend/config/wsgi.py b/{{cookiecutter.project_slug}}/backend/config/wsgi.py deleted file mode 100644 index a7de581c..00000000 --- a/{{cookiecutter.project_slug}}/backend/config/wsgi.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -WSGI config for {{ cookiecutter.project_name }} project. - -This module contains the WSGI application used by Django's development server -and any production WSGI deployments. It should expose a module-level variable -named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover -this application via the ``WSGI_APPLICATION`` setting. - -Usually you will have the standard Django WSGI application here, but it also -might make sense to replace the whole Django WSGI application with a custom one -that later delegates to the Django one. For example, you could introduce WSGI -middleware here, or combine a Django application with an application of another -framework. - -""" -import os -import sys -from pathlib import Path - -from django.core.wsgi import get_wsgi_application - -# This allows easy placement of apps within the interior -# {{ cookiecutter.project_slug }} directory. -ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent -sys.path.append(str(ROOT_DIR / "{{ cookiecutter.project_slug }}")) -# We defer to a DJANGO_SETTINGS_MODULE already in the environment. This breaks -# if running multiple sites in the same mod_wsgi process. To fix this, use -# mod_wsgi daemon mode with each site in its own daemon process, or use -# os.environ["DJANGO_SETTINGS_MODULE"] = "config.settings.production" -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.production") - -# This application object is used by any WSGI server configured to use this -# file. This includes Django's development server, if the WSGI_APPLICATION -# setting points here. -application = get_wsgi_application() -# Apply WSGI middleware here. -# from helloworld.wsgi import HelloWorldApplication -# application = HelloWorldApplication(application) diff --git a/{{cookiecutter.project_slug}}/backend/env.example b/{{cookiecutter.project_slug}}/backend/env.example deleted file mode 100644 index 611d3a0c..00000000 --- a/{{cookiecutter.project_slug}}/backend/env.example +++ /dev/null @@ -1,21 +0,0 @@ -# General settings -DJANGO_ADMIN_URL= -DJANGO_SETTINGS_MODULE=config.settings.local -DJANGO_SECRET_KEY=)!@y(_a9@pbbc8d1yidg9v18m1_y*4o(ha5a076*86_#*zxb43 -DJANGO_ALLOWED_HOSTS=.sixfeetup.com - -# AWS Settings -DJANGO_AWS_ACCESS_KEY_ID= -DJANGO_AWS_SECRET_ACCESS_KEY= -DJANGO_AWS_STORAGE_BUCKET_NAME= - -# Used with email -DJANGO_MAILGUN_API_KEY= -DJANGO_SERVER_EMAIL= -MAILGUN_SENDER_DOMAIN= - -# Security! Better to use DNS for this task, but you can use redirect -DJANGO_SECURE_SSL_REDIRECT=False - -# Are we using Vagrant -USE_VAGRANT= diff --git a/{{cookiecutter.project_slug}}/backend/manage.py b/{{cookiecutter.project_slug}}/backend/manage.py deleted file mode 100755 index ca6912d6..00000000 --- a/{{cookiecutter.project_slug}}/backend/manage.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python -import os -import sys - -if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") - - try: - from django.core.management import execute_from_command_line - except ImportError: - # The above import may fail for some other reason. Ensure that the - # issue is really that Django is missing to avoid masking other - # exceptions on Python 2. - try: - import django # noqa - except ImportError: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) - raise - execute_from_command_line(sys.argv) diff --git a/{{cookiecutter.project_slug}}/backend/requirements/base.in b/{{cookiecutter.project_slug}}/backend/requirements/base.in deleted file mode 100644 index 7ecf2c04..00000000 --- a/{{cookiecutter.project_slug}}/backend/requirements/base.in +++ /dev/null @@ -1,29 +0,0 @@ -argon2-cffi -crispy-bootstrap5 -daphne -django -django-allauth -django-crispy-forms -django-environ -django-model-utils -django-redis -Pillow -urllib3 -{% if cookiecutter.use_sentry == 'y' %} -sentry-sdk[django] -{% endif %} - -{%- if cookiecutter.use_celery == "y" %} -celery -django-celery-beat -flower -redis -{%- endif %} - -{%- if cookiecutter.create_nextjs_frontend == "y" %} -strawberry-graphql-django -{%- endif %} - -{%- if cookiecutter.create_nextjs_frontend == "y" %} -django-cors-headers -{%- endif %} diff --git a/{{cookiecutter.project_slug}}/backend/requirements/local.in b/{{cookiecutter.project_slug}}/backend/requirements/local.in deleted file mode 100644 index dc8f684a..00000000 --- a/{{cookiecutter.project_slug}}/backend/requirements/local.in +++ /dev/null @@ -1,9 +0,0 @@ -# Local development dependencies go here --r base.txt - -debugpy -django-debug-toolbar -django-extensions -ipdb -pydevd-pycharm~=233.13135.95 -Werkzeug diff --git a/{{cookiecutter.project_slug}}/backend/requirements/production.in b/{{cookiecutter.project_slug}}/backend/requirements/production.in deleted file mode 100644 index fa51ec75..00000000 --- a/{{cookiecutter.project_slug}}/backend/requirements/production.in +++ /dev/null @@ -1,20 +0,0 @@ -# PRECAUTION: avoid production dependencies that aren't in development - --r base.txt - -gunicorn -psycopg2 -uvicorn[standard] - -# Django -# ------------------------------------------------------------------------------ -django-storages[boto3] # https://github.com/jschneier/django-storages -daphne - -{%- if cookiecutter.mail_service == 'Mailgun' %} -django-anymail[mailgun] # https://github.com/anymail/django-anymail -{%- elif cookiecutter.mail_service == 'Amazon SES' %} -django-anymail[amazon_ses] # https://github.com/anymail/django-anymail -{%- elif cookiecutter.mail_service == 'Other SMTP' %} -django-anymail # https://github.com/anymail/django-anymail -{%- endif %} diff --git a/{{cookiecutter.project_slug}}/backend/requirements/tests.in b/{{cookiecutter.project_slug}}/backend/requirements/tests.in deleted file mode 100644 index aa4340b8..00000000 --- a/{{cookiecutter.project_slug}}/backend/requirements/tests.in +++ /dev/null @@ -1,15 +0,0 @@ -# Test dependencies go here. --r base.txt - -coverage -flake8 -django-test-plus -factory-boy -django-coverage-plugin - -# pytest -pytest-django -pytest-cov -pytest-freezegun -pytest-mock -pytest-sugar diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/__init__.py deleted file mode 100644 index b4056707..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -__version__ = "{{ cookiecutter.version }}" -__version_info__ = tuple( - [ - int(num) if num.isdigit() else num - for num in __version__.replace("-", ".", 1).split(".") - ] -) diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/celery.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/celery.py deleted file mode 100644 index db9aec9f..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/celery.py +++ /dev/null @@ -1,17 +0,0 @@ -import os - -from celery import Celery - -# set the default Django settings module for the 'celery' program. -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local") - -app = Celery("{{ cookiecutter.project_slug }}") - -# Using a string here means the worker doesn't have to serialize -# the configuration object to child processes. -# - namespace='CELERY' means all celery-related configuration keys -# should have a `CELERY_` prefix. -app.config_from_object("django.conf:settings", namespace="CELERY") - -# Load task modules from all registered Django app configs. -app.autodiscover_tasks() diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/admin.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/admin.py deleted file mode 100644 index 9bd3bf98..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/admin.py +++ /dev/null @@ -1,8 +0,0 @@ -from django.contrib import admin - -from .models import Challenge - - -@admin.register(Challenge) -class ChallengeAdmin(admin.ModelAdmin): - list_display = ("id", "is_completed") diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/apps.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/apps.py deleted file mode 100644 index aa671962..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/apps.py +++ /dev/null @@ -1,16 +0,0 @@ -# {{cookiecutter.project_slug}}/challenge/apps.py -from django.apps import AppConfig - - -class ChallengeConfig(AppConfig): - name = "{{cookiecutter.project_slug}}.challenge" - - def ready(self): - from django.db.models.signals import post_migrate - # Connect post-migrate signal to make sure that this comes - # after migrations are done. - post_migrate.connect(self.report_readiness, sender=self) - - def report_readiness(self, **kwargs): - from .utils import report_readiness - report_readiness() diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/migrations/0001_initial.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/migrations/0001_initial.py deleted file mode 100644 index e264ccec..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/migrations/0001_initial.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 5.1.1 on 2024-09-15 01:38 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='Challenge', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('is_completed', models.BooleanField(default=False, help_text='Designates whether scaf challenge is completed or not.', verbose_name='completion status')), - ], - options={ - 'verbose_name': 'challenge', - 'verbose_name_plural': 'challenges', - }, - ), - ] diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/migrations/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/models.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/models.py deleted file mode 100644 index 77ea0740..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/models.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.db import models - - -class Challenge(models.Model): - is_completed = models.BooleanField( - verbose_name="completion status", - help_text="Designates whether scaf challenge is completed or not.", - default=False, - ) - - class Meta: - verbose_name = "challenge" - verbose_name_plural = "challenges" diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/utils.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/utils.py deleted file mode 100644 index b05afa6b..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/challenge/utils.py +++ /dev/null @@ -1,37 +0,0 @@ -import http.client -import json -import logging -import time - -from django.conf import settings - -from .models import Challenge - -logger = logging.getLogger(__name__) - - -def report_readiness(): - if Challenge.objects.filter(is_completed=True).exists(): - logger.info("Challenge already completed") - return - - base_url = settings.CHALLENGE_BASE_URL.replace("https://", "") - conn = http.client.HTTPSConnection(base_url) - payload = json.dumps( - { - "sessionid": settings.CHALLENGE_SESSION_ID, - "end": "{:.6f}".format(time.time()), - } - ) - headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {settings.CHALLENGE_JWT_TOKEN}", - } - conn.request("POST", "/Prod/report", payload, headers) - res = conn.getresponse() - data = res.read().decode("utf-8") - logger.info("Response[%d]: %s", res.status, data) - - if res.status == 200: - Challenge.objects.create(is_completed=True) - logger.info("Challenge completed") diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/conftest.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/conftest.py deleted file mode 100644 index b303ffaf..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/conftest.py +++ /dev/null @@ -1,24 +0,0 @@ -import pytest -{%- if cookiecutter.create_nextjs_frontend == "y" %} -from strawberry_django.test.client import TestClient -{%- endif %} - -from {{ cookiecutter.project_slug }}.users.models import User -from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory - - -@pytest.fixture(autouse=True) -def media_storage(settings, tmpdir): - settings.MEDIA_ROOT = tmpdir.strpath - - -@pytest.fixture -def user() -> User: - return UserFactory() - - -{% if cookiecutter.create_nextjs_frontend == "y" -%} -@pytest.fixture -def graphql_client() -> TestClient: - return TestClient("/graphql/") -{%- endif %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/__init__.py deleted file mode 100644 index 1c7ecc89..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -To understand why this file is here, please read: - -http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django -""" diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/__init__.py deleted file mode 100644 index 1c7ecc89..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -To understand why this file is here, please read: - -http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django -""" diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0001_initial.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0001_initial.py deleted file mode 100644 index 91d43613..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0001_initial.py +++ /dev/null @@ -1,41 +0,0 @@ -import django.contrib.sites.models -from django.contrib.sites.models import _simple_domain_name_validator -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [] - - operations = [ - migrations.CreateModel( - name="Site", - fields=[ - ( - "id", - models.BigAutoField( - verbose_name="ID", - serialize=False, - auto_created=True, - primary_key=True, - ), - ), - ( - "domain", - models.CharField( - max_length=100, - verbose_name="domain name", - validators=[_simple_domain_name_validator], - ), - ), - ("name", models.CharField(max_length=50, verbose_name="display name")), - ], - options={ - "ordering": ("domain",), - "db_table": "django_site", - "verbose_name": "site", - "verbose_name_plural": "sites", - }, - bases=(models.Model,), - managers=[("objects", django.contrib.sites.models.SiteManager())], - ) - ] diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0002_alter_domain_unique.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0002_alter_domain_unique.py deleted file mode 100644 index 4359049f..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0002_alter_domain_unique.py +++ /dev/null @@ -1,19 +0,0 @@ -import django.contrib.sites.models -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [("sites", "0001_initial")] - - operations = [ - migrations.AlterField( - model_name="site", - name="domain", - field=models.CharField( - max_length=100, - unique=True, - validators=[django.contrib.sites.models._simple_domain_name_validator], - verbose_name="domain name", - ), - ) - ] diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0003_set_site_domain_and_name.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0003_set_site_domain_and_name.py deleted file mode 100644 index c56f9806..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/0003_set_site_domain_and_name.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -To understand why this file is here, please read: - -http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django -""" -from django.conf import settings -from django.db import migrations - - -def update_site_forward(apps, schema_editor): - """Set site domain and name.""" - Site = apps.get_model("sites", "Site") - Site.objects.update_or_create( - id=settings.SITE_ID, - defaults={ - "domain": "{{ cookiecutter.domain_name }}", - "name": "{{ cookiecutter.project_name }}", - }, - ) - - -def update_site_backward(apps, schema_editor): - """Revert site domain and name to default.""" - Site = apps.get_model("sites", "Site") - Site.objects.update_or_create( - id=settings.SITE_ID, defaults={"domain": "example.com", "name": "example.com"} - ) - - -class Migration(migrations.Migration): - dependencies = [("sites", "0002_alter_domain_unique")] - - operations = [migrations.RunPython(update_site_forward, update_site_backward)] diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/__init__.py deleted file mode 100644 index 1c7ecc89..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/contrib/sites/migrations/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -""" -To understand why this file is here, please read: - -http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django -""" diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/css/project.css b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/css/project.css deleted file mode 100644 index f1d543da..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/css/project.css +++ /dev/null @@ -1,13 +0,0 @@ -/* These styles are generated from project.scss. */ - -.alert-debug { - color: black; - background-color: white; - border-color: #d6e9c6; -} - -.alert-error { - color: #b94a48; - background-color: #f2dede; - border-color: #eed3d7; -} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/fonts/.gitkeep b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/fonts/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/images/favicons/favicon.ico b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/images/favicons/favicon.ico deleted file mode 100644 index e1c1dd1a32a3a077c41a21e52bc7fb5ac90d3afb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8348 zcmeHLX-gGh6rQ3V&`<D7CE<noAlEjsXwxujXd#F)ld{xou?49lT4^C#DMQg92<lcw zMzolfs1@y^S<!}Aws>92%;lcmGu`Jl^WK@OV`^XKh08PZoaH%l?rdiiWq>kJ2@6vM zhAH8L6=kTRD1!xR`-2o^hS&}loN!U1#gF+=YxEq~uqf5#iBw%p0;w;5ehm+6a!sSu zh;X+$+}oF$X1Q6DwS~>Y_Hpw^(&QvJO<5ZCPrn5l<LUX!$CQ2UuxTFFU@d=5o~T)_ zM&9lX?aYJe)cC!DuyW2Hv#fzNBja7o{yI$k?DQi4Qa1T~osibBqqBpOvgVuShAz;K zmYFZ>aNp%s{<NfD^tq;K$)o9J`Bk|DTDfaUPz^Y4pxH6?go{g!rZ4q%h8hZr&i<2r zT*`Rbm$#it9u?E4ueH?P(XQoh{?VjqRllpGTlcTg>B3x1hf%*?eW>oS{<{4s^u_yG zpDyG!_iV#~G=q<~slG@0Sx47XXQ%O;HY7ILVf}<nvkjKkUq5Z@&&!CV?=8)SJU*X~ zs@_!4mAeIW{>B-)R$6GV^A78)t0tN9`tu3r9Z+xM?NgUd8geu=c`0?r;-KR&IQjKs zSB#VCpg8CPW&M}$sth@H=VS%t;23!!j};F)bb;W3EkA!4QmCsY_p81^T<lC2Jw<JL zl>K0{;$g>e1Hl998^0M+r0-7ZSN+l_cMSRuEALTE@|d6+3{GMP^;_|<<G6v~fm@Db z$SJ7$Z6)nIxtS6-&!vT#DsfNbg?K9-cIX1Z>yhubb{FF1IPgH|0>SH%pC!c)uFI)H z?jv4y0uO{P5WE>~I<$r!RFo0lN4r{xm;Jy4p$h~b3S*a#)$Z*nI}&Kc_C+*zZHz1v zIR8TBVH<RTUHMzt<pQkyWFERe+1}lKD}5^-d7%pgZx^j}ta#*yE)cw3G}D>7Y?Mp~ zofpsr+SP@>EX4e*bQ{nAUYtKrQ&-5d4j;FF{^-^Dt2^5I`HSb!|22PN26n3>hKPOy zW<i`2eS&}fZx3to{LSA9#ODI-3qh#w1a37VHY(or(QZwVGl$n`v8t<fVnSrlb)f&h zX0M(~Jg?;!WC#2>2D*A*v+c{bFKCwozbB{dObp~e&1Nxrj<4Ih4~w)M`nl08o}Wq2 z#Jt(k+M>+}JY(=2gm(gdUq)^@e%tX(F)RBtotnB2^y>YKz-5eg_qO&n%lJ1nuQmTY zxmyE1NWjl1EGvD?Z|n;neT;sa?Q;Ef-#%$BYxXAhD4xF+@M>*qrR!x^sPN98|BX4; z!$NJcKF`^C7f(<_vlp%b>`pxL^8Y<&?KFx{n_!5C9VqLA*CP@zhXs2t#dmrAKu?d_ y^&_r5_e@uesG}CO*g!3o?-kB+I^cA`>44J#rvpw0oDMi0a5~_0!0Eu>4*Uj$LD0AW diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/js/project.js b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/js/project.js deleted file mode 100644 index d26d23b9..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/js/project.js +++ /dev/null @@ -1 +0,0 @@ -/* Project specific Javascript goes here. */ diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/sass/project.scss b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/sass/project.scss deleted file mode 100644 index ac8348c3..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/static/sass/project.scss +++ /dev/null @@ -1,35 +0,0 @@ -@import "bootstrap"; - -// project specific CSS goes here - -//////////////////////////////// -//Variables// -//////////////////////////////// - -// Alert colors - -$white: #fff; -$mint-green: #d6e9c6; -$black: #000; -$pink: #f2dede; -$dark-pink: #eed3d7; -$red: #b94a48; - -//////////////////////////////// -//Alerts// -//////////////////////////////// - -// bootstrap alert CSS, translated to the django-standard levels of -// debug, info, success, warning, error - -.alert-debug { - background-color: $white; - border-color: $mint-green; - color: $black; -} - -.alert-error { - background-color: $pink; - border-color: $dark-pink; - color: $red; -} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/403.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/403.html deleted file mode 100644 index c02bd4e9..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/403.html +++ /dev/null @@ -1,9 +0,0 @@ -{% raw %}{% extends "base.html" %} - -{% block title %}Forbidden (403){% endblock %} - -{% block content %} -<h1>Forbidden (403)</h1> - -<p>CSRF verification failed. Request aborted.</p> -{% endblock content %}{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/404.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/404.html deleted file mode 100644 index 1687ef31..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/404.html +++ /dev/null @@ -1,9 +0,0 @@ -{% raw %}{% extends "base.html" %} - -{% block title %}Page not found{% endblock %} - -{% block content %} -<h1>Page not found</h1> - -<p>This is not the page you were looking for.</p> -{% endblock content %}{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/500.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/500.html deleted file mode 100644 index 122e0813..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/500.html +++ /dev/null @@ -1,13 +0,0 @@ -{% raw %}{% extends "base.html" %} - -{% block title %}Server Error{% endblock %} - -{% block content %} -<h1>Ooops!!! 500</h1> - -<h3>Looks like something went wrong!</h3> - -<p>We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.</p> -{% endblock content %} - -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/account_inactive.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/account_inactive.html deleted file mode 100644 index fe9b6807..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/account_inactive.html +++ /dev/null @@ -1,12 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} - -{% block head_title %}{% trans "Account Inactive" %}{% endblock %} - -{% block inner %} -<h1>{% trans "Account Inactive" %}</h1> - -<p>{% trans "This account is inactive." %}</p> -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/base.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/base.html deleted file mode 100644 index cd07bbab..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/base.html +++ /dev/null @@ -1,11 +0,0 @@ -{% raw %}{% extends "base.html" %} -{% block title %}{% block head_title %}{% endblock head_title %}{% endblock title %} - -{% block content %} -<div class="row"> - <div class="col-md-6 offset-md-3"> - {% block inner %}{% endblock %} - </div> -</div> -{% endblock %} -{% endraw %} \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/email.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/email.html deleted file mode 100644 index 78d99736..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/email.html +++ /dev/null @@ -1,80 +0,0 @@ -{% raw %} -{% extends "account/base.html" %} - -{% load i18n %} -{% load crispy_forms_tags %} - -{% block head_title %}{% trans "Account" %}{% endblock %} - -{% block inner %} -<h1>{% trans "E-mail Addresses" %}</h1> - -{% if user.emailaddress_set.all %} -<p>{% trans 'The following e-mail addresses are associated with your account:' %}</p> - -<form action="{% url 'account_email' %}" class="email_list" method="post"> -{% csrf_token %} -<fieldset class="blockLabels"> - - {% for emailaddress in user.emailaddress_set.all %} -<div class="radio"> - <label for="email_radio_{{forloop.counter}}" class="{% if emailaddress.primary %}primary_email{%endif%}"> - - <input id="email_radio_{{forloop.counter}}" type="radio" name="email" {% if emailaddress.primary or user.emailaddress_set.count == 1 %}checked="checked"{%endif %} value="{{emailaddress.email}}"/> - - {{ emailaddress.email }} - {% if emailaddress.verified %} - <span class="verified">{% trans "Verified" %}</span> - {% else %} - <span class="unverified">{% trans "Unverified" %}</span> - {% endif %} - {% if emailaddress.primary %}<span class="primary">{% trans "Primary" %}</span>{% endif %} - </label> -</div> - {% endfor %} - -<div class="form-group"> - <button class="secondaryAction btn btn-primary" type="submit" name="action_primary" >{% trans 'Make Primary' %}</button> - <button class="secondaryAction btn btn-primary" type="submit" name="action_send" >{% trans 'Re-send Verification' %}</button> - <button class="primaryAction btn btn-primary" type="submit" name="action_remove" >{% trans 'Remove' %}</button> -</div> - -</fieldset> -</form> - -{% else %} -<p><strong>{% trans 'Warning:'%}</strong> {% trans "You currently do not have any e-mail address set up. You should really add an e-mail address so you can receive notifications, reset your password, etc." %}</p> - -{% endif %} - - - <h2>{% trans "Add E-mail Address" %}</h2> - - <form method="post" action="{% url 'account_email' %}" class="add_email"> - {% csrf_token %} - {{ form|crispy }} - <button class="btn btn-primary" name="action_add" type="submit">{% trans "Add E-mail" %}</button> - </form> - -{% endblock %} - - -{% block javascript %} -{{ block.super }} -<script type="text/javascript"> -(function() { - var message = "{% trans 'Do you really want to remove the selected e-mail address?' %}"; - var actions = document.getElementsByName('action_remove'); - if (actions.length) { - actions[0].addEventListener("click", function(e) { - if (! confirm(message)) { - e.preventDefault(); - } - }); - } -})(); - -$('.form-group').removeClass('row'); -</script> -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/email_confirm.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/email_confirm.html deleted file mode 100644 index eb45cf60..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/email_confirm.html +++ /dev/null @@ -1,32 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% load account %} - -{% block head_title %}{% trans "Confirm E-mail Address" %}{% endblock %} - - -{% block inner %} -<h1>{% trans "Confirm E-mail Address" %}</h1> - -{% if confirmation %} - -{% user_display confirmation.email_address.user as user_display %} - -<p>{% blocktrans with confirmation.email_address.email as email %}Please confirm that <a href="mailto:{{ email }}">{{ email }}</a> is an e-mail address for user {{ user_display }}.{% endblocktrans %}</p> - -<form method="post" action="{% url 'account_confirm_email' confirmation.key %}"> -{% csrf_token %} - <button class="btn btn-primary" type="submit">{% trans 'Confirm' %}</button> -</form> - -{% else %} - -{% url 'account_email' as email_url %} - -<p>{% blocktrans %}This e-mail confirmation link expired or is invalid. Please <a href="{{ email_url }}">issue a new e-mail confirmation request</a>.{% endblocktrans %}</p> - -{% endif %} - -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/login.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/login.html deleted file mode 100644 index a7193222..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/login.html +++ /dev/null @@ -1,48 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% load account socialaccount %} -{% load crispy_forms_tags %} - -{% block head_title %}{% trans "Sign In" %}{% endblock %} - -{% block inner %} - -<h1>{% trans "Sign In" %}</h1> - -{% get_providers as socialaccount_providers %} - -{% if socialaccount_providers %} -<p>{% blocktrans with site.name as site_name %}Please sign in with one -of your existing third party accounts. Or, <a href="{{ signup_url }}">sign up</a> -for a {{ site_name }} account and sign in below:{% endblocktrans %}</p> - -<div class="socialaccount_ballot"> - - <ul class="socialaccount_providers"> - {% include "socialaccount/snippets/provider_list.html" with process="login" %} - </ul> - - <div class="login-or">{% trans 'or' %}</div> - -</div> - -{% include "socialaccount/snippets/login_extra.html" %} - -{% else %} -<p>{% blocktrans %}If you have not created an account yet, then please -<a href="{{ signup_url }}">sign up</a> first.{% endblocktrans %}</p> -{% endif %} - -<form class="login" method="POST" action="{% url 'account_login' %}"> - {% csrf_token %} - {{ form|crispy }} - {% if redirect_field_value %} - <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" /> - {% endif %} - <a class="button secondaryAction" href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a> - <button class="primaryAction btn btn-primary" type="submit">{% trans "Sign In" %}</button> -</form> - -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/logout.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/logout.html deleted file mode 100644 index baa8183c..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/logout.html +++ /dev/null @@ -1,22 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} - -{% block head_title %}{% trans "Sign Out" %}{% endblock %} - -{% block inner %} -<h1>{% trans "Sign Out" %}</h1> - -<p>{% trans 'Are you sure you want to sign out?' %}</p> - -<form method="post" action="{% url 'account_logout' %}"> - {% csrf_token %} - {% if redirect_field_value %} - <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}"/> - {% endif %} - <button class="btn btn-danger" type="submit">{% trans 'Sign Out' %}</button> -</form> - - -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_change.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_change.html deleted file mode 100644 index 62bbbc13..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_change.html +++ /dev/null @@ -1,17 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% load crispy_forms_tags %} - -{% block head_title %}{% trans "Change Password" %}{% endblock %} - -{% block inner %} - <h1>{% trans "Change Password" %}</h1> - - <form method="POST" action="{% url 'account_change_password' %}" class="password_change"> - {% csrf_token %} - {{ form|crispy }} - <button class="btn btn-primary" type="submit" name="action">{% trans "Change Password" %}</button> - </form> -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset.html deleted file mode 100644 index b9869fb2..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset.html +++ /dev/null @@ -1,26 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% load account %} -{% load crispy_forms_tags %} - -{% block head_title %}{% trans "Password Reset" %}{% endblock %} - -{% block inner %} - - <h1>{% trans "Password Reset" %}</h1> - {% if user.is_authenticated %} - {% include "account/snippets/already_logged_in.html" %} - {% endif %} - - <p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll send you an e-mail allowing you to reset it." %}</p> - - <form method="POST" action="{% url 'account_reset_password' %}" class="password_reset"> - {% csrf_token %} - {{ form|crispy }} - <input class="btn btn-primary" type="submit" value="{% trans 'Reset My Password' %}" /> - </form> - - <p>{% blocktrans %}Please contact us if you have any trouble resetting your password.{% endblocktrans %}</p> -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_done.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_done.html deleted file mode 100644 index cf2129b1..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_done.html +++ /dev/null @@ -1,17 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% load account %} - -{% block head_title %}{% trans "Password Reset" %}{% endblock %} - -{% block inner %} - <h1>{% trans "Password Reset" %}</h1> - - {% if user.is_authenticated %} - {% include "account/snippets/already_logged_in.html" %} - {% endif %} - - <p>{% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}</p> -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html deleted file mode 100644 index 671eb12c..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key.html +++ /dev/null @@ -1,25 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% load crispy_forms_tags %} -{% block head_title %}{% trans "Change Password" %}{% endblock %} - -{% block inner %} - <h1>{% if token_fail %}{% trans "Bad Token" %}{% else %}{% trans "Change Password" %}{% endif %}</h1> - - {% if token_fail %} - {% url 'account_reset_password' as passwd_reset_url %} - <p>{% blocktrans %}The password reset link was invalid, possibly because it has already been used. Please request a <a href="{{ passwd_reset_url }}">new password reset</a>.{% endblocktrans %}</p> - {% else %} - {% if form %} - <form method="POST" action="."> - {% csrf_token %} - {{ form|crispy }} - <input class="btn btn-primary" type="submit" name="action" value="{% trans 'change password' %}"/> - </form> - {% else %} - <p>{% trans 'Your password is now changed.' %}</p> - {% endif %} - {% endif %} -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html deleted file mode 100644 index 925b7aa2..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_reset_from_key_done.html +++ /dev/null @@ -1,10 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% block head_title %}{% trans "Change Password" %}{% endblock %} - -{% block inner %} - <h1>{% trans "Change Password" %}</h1> - <p>{% trans 'Your password is now changed.' %}</p> -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_set.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_set.html deleted file mode 100644 index 563a0b18..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/password_set.html +++ /dev/null @@ -1,17 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% load crispy_forms_tags %} - -{% block head_title %}{% trans "Set Password" %}{% endblock %} - -{% block inner %} - <h1>{% trans "Set Password" %}</h1> - - <form method="POST" action="{% url 'account_set_password' %}" class="password_set"> - {% csrf_token %} - {{ form|crispy }} - <input class="btn btn-primary" type="submit" name="action" value="{% trans 'Set Password' %}"/> - </form> -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/signup.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/signup.html deleted file mode 100644 index 80490a2e..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/signup.html +++ /dev/null @@ -1,23 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} -{% load crispy_forms_tags %} - -{% block head_title %}{% trans "Signup" %}{% endblock %} - -{% block inner %} -<h1>{% trans "Sign Up" %}</h1> - -<p>{% blocktrans %}Already have an account? Then please <a href="{{ login_url }}">sign in</a>.{% endblocktrans %}</p> - -<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}"> - {% csrf_token %} - {{ form|crispy }} - {% if redirect_field_value %} - <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" /> - {% endif %} - <button class="btn btn-primary" type="submit">{% trans "Sign Up" %} »</button> -</form> - -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/signup_closed.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/signup_closed.html deleted file mode 100644 index eca9b156..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/signup_closed.html +++ /dev/null @@ -1,12 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} - -{% block head_title %}{% trans "Sign Up Closed" %}{% endblock %} - -{% block inner %} -<h1>{% trans "Sign Up Closed" %}</h1> - -<p>{% trans "We are sorry, but the sign up is currently closed." %}</p> -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/verification_sent.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/verification_sent.html deleted file mode 100644 index ccc8d9a1..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/verification_sent.html +++ /dev/null @@ -1,13 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} - -{% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} - -{% block inner %} - <h1>{% trans "Verify Your E-mail Address" %}</h1> - - <p>{% blocktrans %}We have sent an e-mail to you for verification. Follow the link provided to finalize the signup process. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}</p> - -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/verified_email_required.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/verified_email_required.html deleted file mode 100644 index f3078b68..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/account/verified_email_required.html +++ /dev/null @@ -1,24 +0,0 @@ -{% raw %}{% extends "account/base.html" %} - -{% load i18n %} - -{% block head_title %}{% trans "Verify Your E-mail Address" %}{% endblock %} - -{% block inner %} -<h1>{% trans "Verify Your E-mail Address" %}</h1> - -{% url 'account_email' as email_url %} - -<p>{% blocktrans %}This part of the site requires us to verify that -you are who you claim to be. For this purpose, we require that you -verify ownership of your e-mail address. {% endblocktrans %}</p> - -<p>{% blocktrans %}We have sent an e-mail to you for -verification. Please click on the link inside this e-mail. Please -contact us if you do not receive it within a few minutes.{% endblocktrans %}</p> - -<p>{% blocktrans %}<strong>Note:</strong> you can still <a href="{{ email_url }}">change your e-mail address</a>.{% endblocktrans %}</p> - - -{% endblock %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/base.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/base.html deleted file mode 100644 index 77ca6ae6..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/base.html +++ /dev/null @@ -1,106 +0,0 @@ -{% raw %}{% load static i18n {% endraw %}{% raw %}%}<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"> - <meta http-equiv="x-ua-compatible" content="ie=edge"> - <title>{% block title %}{% endraw %}{{ cookiecutter.project_name }}{% raw %}{% endblock title %}</title> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - <meta name="description" content=""> - <meta name="author" content=""> - - <!-- HTML5 shim, for IE6-8 support of HTML5 elements --> - <!--[if lt IE 9]> - <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script> - <![endif]--> - - <link rel="icon" href="{% static 'images/favicons/favicon.ico' %}"> - - {% block css %} - {% endraw %}{% raw %} - <!-- Latest compiled and minified Bootstrap CSS --> - <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> - {% endraw %}{% raw %} - - <!-- Your stuff: Third-party CSS libraries go here --> - - <!-- This file stores project-specific CSS --> - <link href="{% static 'css/project.css' %}" rel="stylesheet"> - {% endblock %} - - </head> - - <body> - - <div class="mb-1"> - <nav class="navbar navbar-expand-md navbar-light bg-light"> - <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> - <span class="navbar-toggler-icon"></span> - </button> - <a class="navbar-brand" href="{% url 'home' %}">{% endraw %}{{ cookiecutter.project_name }}{% raw %}</a> - - <div class="collapse navbar-collapse" id="navbarSupportedContent"> - <ul class="navbar-nav mr-auto"> - <li class="nav-item active"> - <a class="nav-link" href="{% url 'home' %}">Home <span class="sr-only">(current)</span></a> - </li> - <li class="nav-item"> - <a class="nav-link" href="{% url 'about' %}">About</a> - </li> - {% if request.user.is_authenticated %} - <li class="nav-item"> - {# URL provided by django-allauth/account/urls.py #} - <a class="nav-link" href="{% url 'users:detail' request.user.username %}">{% trans "My Profile" %}</a> - </li> - <li class="nav-item"> - {# URL provided by django-allauth/account/urls.py #} - <a class="nav-link" href="{% url 'account_logout' %}">{% trans "Sign Out" %}</a> - </li> - {% else %} - <li class="nav-item"> - {# URL provided by django-allauth/account/urls.py #} - <a id="sign-up-link" class="nav-link" href="{% url 'account_signup' %}">{% trans "Sign Up" %}</a> - </li> - <li class="nav-item"> - {# URL provided by django-allauth/account/urls.py #} - <a id="log-in-link" class="nav-link" href="{% url 'account_login' %}">{% trans "Sign In" %}</a> - </li> - {% endif %} - </ul> - </div> - </nav> - - </div> - - <div class="container"> - - {% if messages %} - {% for message in messages %} - <div class="alert {% if message.tags %}alert-{{ message.tags }}{% endif %}">{{ message }}<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button></div> - {% endfor %} - {% endif %} - - {% block content %} - <p>Welcome to your brand-new <a href="https://github.com/sixfeetup/scaf">Scaf</a>-powered Django project! Your development journey starts here. Explore, build, and innovate with speed and ease.</p> - {% endblock content %} - - </div> <!-- /container --> - - {% block modal %}{% endblock modal %} - - <!-- Le javascript - ================================================== --> - <!-- Placed at the end of the document so the pages load faster --> - {% block javascript %} - <!-- Bootstrap JS and its dependencies--> - <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> - <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> - <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> - - <!-- Your stuff: Third-party javascript libraries go here --> - - <!-- place project specific Javascript in this file --> - <script src="{% static 'js/project.js' %}"></script> - {% endblock javascript %} - </body> -</html> - {% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/pages/about.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/pages/about.html deleted file mode 100644 index 94beff9c..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/pages/about.html +++ /dev/null @@ -1 +0,0 @@ -{% raw %}{% extends "base.html" %}{% endraw %} \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/pages/home.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/pages/home.html deleted file mode 100644 index 94beff9c..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/pages/home.html +++ /dev/null @@ -1 +0,0 @@ -{% raw %}{% extends "base.html" %}{% endraw %} \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/users/user_detail.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/users/user_detail.html deleted file mode 100644 index 47b61122..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/users/user_detail.html +++ /dev/null @@ -1,36 +0,0 @@ -{% raw %}{% extends "base.html" %} -{% load static %} - -{% block title %}User: {{ object.username }}{% endblock %} - -{% block content %} -<div class="container"> - - <div class="row"> - <div class="col-sm-12"> - - <h2>{{ object.username }}</h2> - {% if object.name %} - <p>{{ object.name }}</p> - {% endif %} - </div> - </div> - -{% if object == request.user %} -<!-- Action buttons --> -<div class="row"> - - <div class="col-sm-12"> - <a class="btn btn-primary" href="{% url 'users:update' %}" role="button">My Info</a> - <a class="btn btn-primary" href="{% url 'account_email' %}" role="button">E-Mail</a> - <!-- Your Stuff: Custom user template urls --> - </div> - -</div> -<!-- End Action buttons --> -{% endif %} - - -</div> -{% endblock content %} -{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/users/user_form.html b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/users/user_form.html deleted file mode 100644 index e9da0d48..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/templates/users/user_form.html +++ /dev/null @@ -1,17 +0,0 @@ -{% raw %}{% extends "base.html" %} -{% load crispy_forms_tags %} - -{% block title %}{{ user.username }}{% endblock %} - -{% block content %} - <h1>{{ user.username }}</h1> - <form class="form-horizontal" method="post" action="{% url 'users:update' %}"> - {% csrf_token %} - {{ form|crispy }} - <div class="control-group"> - <div class="controls"> - <button type="submit" class="btn btn-primary">Update</button> - </div> - </div> - </form> -{% endblock %}{% endraw %} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/adapters.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/adapters.py deleted file mode 100644 index 0d206fae..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/adapters.py +++ /dev/null @@ -1,16 +0,0 @@ -from typing import Any - -from allauth.account.adapter import DefaultAccountAdapter -from allauth.socialaccount.adapter import DefaultSocialAccountAdapter -from django.conf import settings -from django.http import HttpRequest - - -class AccountAdapter(DefaultAccountAdapter): - def is_open_for_signup(self, request: HttpRequest): - return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True) - - -class SocialAccountAdapter(DefaultSocialAccountAdapter): - def is_open_for_signup(self, request: HttpRequest, sociallogin: Any): - return getattr(settings, "ACCOUNT_ALLOW_REGISTRATION", True) diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/admin.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/admin.py deleted file mode 100644 index 7c95eccc..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/admin.py +++ /dev/null @@ -1,16 +0,0 @@ -from django.contrib import admin -from django.contrib.auth import admin as auth_admin -from django.contrib.auth import get_user_model - -from {{ cookiecutter.project_slug }}.users.forms import UserChangeForm, UserCreationForm - -User = get_user_model() - - -@admin.register(User) -class UserAdmin(auth_admin.UserAdmin): - form = UserChangeForm - add_form = UserCreationForm - fieldsets = (("User", {"fields": ("name",)}),) + auth_admin.UserAdmin.fieldsets - list_display = ["username", "name", "is_superuser"] - search_fields = ["name"] diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/apps.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/apps.py deleted file mode 100644 index 2241e5eb..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/apps.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.apps import AppConfig -from django.utils.translation import gettext_lazy as _ - - -class UsersConfig(AppConfig): - name = "{{ cookiecutter.project_slug }}.users" - verbose_name = _("Users") - - def ready(self): - try: - import {{ cookiecutter.project_slug }}.users.signals # noqa F401 - except ImportError: - pass diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/forms.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/forms.py deleted file mode 100644 index cf4b25a5..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/forms.py +++ /dev/null @@ -1,29 +0,0 @@ -from django.contrib.auth import forms, get_user_model -from django.core.exceptions import ValidationError -from django.utils.translation import gettext_lazy as _ - -User = get_user_model() - - -class UserChangeForm(forms.UserChangeForm): - class Meta(forms.UserChangeForm.Meta): - model = User - - -class UserCreationForm(forms.UserCreationForm): - error_message = forms.UserCreationForm.error_messages.update( - {"duplicate_username": _("This username has already been taken.")} - ) - - class Meta(forms.UserCreationForm.Meta): - model = User - - def clean_username(self): - username = self.cleaned_data["username"] - - try: - User.objects.get(username=username) - except User.DoesNotExist: - return username - - raise ValidationError(self.error_messages["duplicate_username"]) diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py deleted file mode 100644 index b0e6bd50..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py +++ /dev/null @@ -1,131 +0,0 @@ -import django.contrib.auth.models -import django.contrib.auth.validators -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - initial = True - - dependencies = [("auth", "0008_alter_user_username_max_length")] - - operations = [ - migrations.CreateModel( - name="User", - fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("password", models.CharField(max_length=128, verbose_name="password")), - ( - "last_login", - models.DateTimeField( - blank=True, null=True, verbose_name="last login" - ), - ), - ( - "is_superuser", - models.BooleanField( - default=False, - help_text="Designates that this user has all permissions without explicitly assigning them.", - verbose_name="superuser status", - ), - ), - ( - "username", - models.CharField( - error_messages={ - "unique": "A user with that username already exists." - }, - help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.", - max_length=150, - unique=True, - validators=[ - django.contrib.auth.validators.UnicodeUsernameValidator() - ], - verbose_name="username", - ), - ), - ( - "first_name", - models.CharField( - blank=True, max_length=30, verbose_name="first name" - ), - ), - ( - "last_name", - models.CharField( - blank=True, max_length=150, verbose_name="last name" - ), - ), - ( - "email", - models.EmailField( - blank=True, max_length=254, verbose_name="email address" - ), - ), - ( - "is_staff", - models.BooleanField( - default=False, - help_text="Designates whether the user can log into this admin site.", - verbose_name="staff status", - ), - ), - ( - "is_active", - models.BooleanField( - default=True, - help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.", - verbose_name="active", - ), - ), - ( - "date_joined", - models.DateTimeField( - default=django.utils.timezone.now, verbose_name="date joined" - ), - ), - ( - "name", - models.CharField( - blank=True, max_length=255, verbose_name="Name of User" - ), - ), - ( - "groups", - models.ManyToManyField( - blank=True, - help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.", - related_name="user_set", - related_query_name="user", - to="auth.Group", - verbose_name="groups", - ), - ), - ( - "user_permissions", - models.ManyToManyField( - blank=True, - help_text="Specific permissions for this user.", - related_name="user_set", - related_query_name="user", - to="auth.Permission", - verbose_name="user permissions", - ), - ), - ], - options={ - "verbose_name_plural": "users", - "verbose_name": "user", - "abstract": False, - }, - managers=[("objects", django.contrib.auth.models.UserManager())], - ) - ] diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/migrations/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/migrations/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/models.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/models.py deleted file mode 100644 index 653012d8..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/models.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.contrib.auth.models import AbstractUser -from django.db.models import CharField -from django.urls import reverse -from django.utils.translation import gettext_lazy as _ - - -class User(AbstractUser): - # First Name and Last Name do not cover name patterns - # around the globe. - name = CharField(_("Name of User"), blank=True, max_length=255) - - def get_absolute_url(self): - return reverse("users:detail", kwargs={"username": self.username}) diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/mutations.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/mutations.py deleted file mode 100644 index 32e5fa95..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/mutations.py +++ /dev/null @@ -1,35 +0,0 @@ -import strawberry -import strawberry_django -from django.contrib.auth import get_user_model -from strawberry_django import mutations - -from .types import UserType - -User = get_user_model() - - -@strawberry_django.input(User) -class UserRegistrationInput: - username: strawberry.auto - password: strawberry.auto - - -@strawberry_django.partial(User) -class UserPartialUpdateInput: - id: strawberry.auto - name: strawberry.auto - - -@strawberry.type -class UserMutation: - """ - User mutations - """ - - # Auth mutations - login: UserType = strawberry_django.auth.login() - logout = strawberry_django.auth.logout() - register: UserType = strawberry_django.auth.register(UserRegistrationInput) - - # User mutations - update_user: UserType = mutations.update(UserPartialUpdateInput) diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/queries.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/queries.py deleted file mode 100644 index 1a09bc5c..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/queries.py +++ /dev/null @@ -1,13 +0,0 @@ -import strawberry -import strawberry_django - -from .types import UserType - - -@strawberry.type -class UserQuery: - """ - User queries - """ - - me: UserType = strawberry_django.auth.current_user() diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tasks.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tasks.py deleted file mode 100644 index c99341c5..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tasks.py +++ /dev/null @@ -1,11 +0,0 @@ -from django.contrib.auth import get_user_model - -from config import celery_app - -User = get_user_model() - - -@celery_app.task() -def get_users_count(): - """A pointless Celery task to demonstrate usage.""" - return User.objects.count() diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/factories.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/factories.py deleted file mode 100644 index 36f96343..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/factories.py +++ /dev/null @@ -1,32 +0,0 @@ -from collections.abc import Sequence -from typing import Any - -from django.contrib.auth import get_user_model -from factory import Faker, post_generation -from factory.django import DjangoModelFactory - - -class UserFactory(DjangoModelFactory): - username = Faker("user_name") - email = Faker("email") - name = Faker("name") - - @post_generation - def password(self, create: bool, extracted: Sequence[Any], **kwargs): - password = ( - extracted - if extracted - else Faker( - "password", - length=42, - special_chars=True, - digits=True, - upper_case=True, - lower_case=True, - ).evaluate(None, None, extra={"locale": None}) - ) - self.set_password(password) - - class Meta: - model = get_user_model() - django_get_or_create = ["username"] diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_forms.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_forms.py deleted file mode 100644 index dfa5da52..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_forms.py +++ /dev/null @@ -1,40 +0,0 @@ -import pytest - -from {{ cookiecutter.project_slug }}.users.forms import UserCreationForm -from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory - -pytestmark = pytest.mark.django_db - - -class TestUserCreationForm: - def test_clean_username(self): - # A user with proto_user params does not exist yet. - proto_user = UserFactory.build() - - form = UserCreationForm( - { - "username": proto_user.username, - "password1": proto_user._password, - "password2": proto_user._password, - } - ) - - assert form.is_valid() - assert form.clean_username() == proto_user.username - - # Creating a user. - form.save() - - # The user with proto_user params already exists, - # hence cannot be created. - form = UserCreationForm( - { - "username": proto_user.username, - "password1": proto_user._password, - "password2": proto_user._password, - } - ) - - assert not form.is_valid() - assert len(form.errors) == 1 - assert "username" in form.errors diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_graphql_views.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_graphql_views.py deleted file mode 100644 index d3cbd696..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_graphql_views.py +++ /dev/null @@ -1,122 +0,0 @@ -import pytest -from strawberry_django.test.client import TestClient - -from {{ cookiecutter.project_slug }}.users.models import User - -pytestmark = pytest.mark.django_db - - -class TestGraphQLView: - """ - Tests for the GraphQL view. - """ - - def test_me_unauthenticated(self, graphql_client: TestClient): - """ - Test that the `me` query does not work when the user is not logged in. - """ - res = graphql_client.query( - """ - query Me { - me { - id - username - name - email - isStaff - isActive - } - } - """, - asserts_errors=False, - ) - assert res.data == None - assert res.errors[0]["message"] == "User is not logged in." - - def test_me_authenticated(self, user: User, graphql_client: TestClient): - """ - Test that the `me` query returns the user information if authenticated. - """ - with graphql_client.login(user): - res = graphql_client.query( - """ - query Me { - me { - email - id - isActive - isStaff - name - username - } - } - """ - ) - - assert res.errors is None - assert res.data == { - "me": { - "id": str(user.id), - "email": user.email, - "name": user.name, - "username": user.username, - "isActive": user.is_active, - "isStaff": user.is_staff, - }, - } - - def test_update_user_unauthenticated(self, graphql_client: TestClient): - """ - Test that the `update_user` mutation does not allow unauthenticated users. - """ - res = graphql_client.query( - """ - mutation MyMutation { - updateUser(input: {id: 1 name: "John Doe"}) { - ... on UserType { - id - email - name - } - } - } - """ - ) - - assert res.errors is None - assert res.data == {"updateUser": {}} - - def test_update_user_authenticated(self, user: User, graphql_client: TestClient): - """ - Test that the `update_user` mutation is updating user information. - """ - expected_name = "John Doe" - with graphql_client.login(user): - res = graphql_client.query( - """ - mutation UpdateUser($input: UserPartialUpdateInput!) { - updateUser(input: $input) { - ... on UserType { - id - email - name - } - } - } - """, - variables={ - "input": { - "id": str(user.id), - "name": expected_name - } - }, - ) - - assert res.errors is None - assert res.data == { - "updateUser": { - "id": str(user.id), - "email": user.email, - "name": expected_name, - } - } diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_models.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_models.py deleted file mode 100644 index 3194be1f..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_models.py +++ /dev/null @@ -1,9 +0,0 @@ -import pytest - -from {{ cookiecutter.project_slug }}.users.models import User - -pytestmark = pytest.mark.django_db - - -def test_user_get_absolute_url(user: User): - assert user.get_absolute_url() == f"/users/{user.username}/" diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_tasks.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_tasks.py deleted file mode 100644 index 41d5af29..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_tasks.py +++ /dev/null @@ -1,16 +0,0 @@ -import pytest -from celery.result import EagerResult - -from {{ cookiecutter.project_slug }}.users.tasks import get_users_count -from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory - -pytestmark = pytest.mark.django_db - - -def test_user_count(settings): - """A basic test to execute the get_users_count Celery task.""" - UserFactory.create_batch(3) - settings.CELERY_TASK_ALWAYS_EAGER = True - task_result = get_users_count.delay() - assert isinstance(task_result, EagerResult) - assert task_result.result == 3 diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_urls.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_urls.py deleted file mode 100644 index aab6d0a8..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_urls.py +++ /dev/null @@ -1,24 +0,0 @@ -import pytest -from django.urls import resolve, reverse - -from {{ cookiecutter.project_slug }}.users.models import User - -pytestmark = pytest.mark.django_db - - -def test_detail(user: User): - assert ( - reverse("users:detail", kwargs={"username": user.username}) - == f"/users/{user.username}/" - ) - assert resolve(f"/users/{user.username}/").view_name == "users:detail" - - -def test_update(): - assert reverse("users:update") == "/users/~update/" - assert resolve("/users/~update/").view_name == "users:update" - - -def test_redirect(): - assert reverse("users:redirect") == "/users/~redirect/" - assert resolve("/users/~redirect/").view_name == "users:redirect" diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_views.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_views.py deleted file mode 100644 index 18b8da7a..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/tests/test_views.py +++ /dev/null @@ -1,79 +0,0 @@ -import pytest -from django.contrib.auth.models import AnonymousUser -from django.http.response import Http404 -from django.test import RequestFactory - -from {{ cookiecutter.project_slug }}.users.models import User -from {{ cookiecutter.project_slug }}.users.tests.factories import UserFactory -from {{ cookiecutter.project_slug }}.users.views import ( - UserRedirectView, - UserUpdateView, - user_detail_view, -) - -pytestmark = pytest.mark.django_db - - -class TestUserUpdateView: - """ - TODO: - extracting view initialization code as class-scoped fixture - would be great if only pytest-django supported non-function-scoped - fixture db access -- this is a work-in-progress for now: - https://github.com/pytest-dev/pytest-django/pull/258 - """ - - def test_get_success_url(self, user: User, rf: RequestFactory): - view = UserUpdateView() - request = rf.get("/fake-url/") - request.user = user - - view.request = request - - assert view.get_success_url() == f"/users/{user.username}/" - - def test_get_object(self, user: User, rf: RequestFactory): - view = UserUpdateView() - request = rf.get("/fake-url/") - request.user = user - - view.request = request - - assert view.get_object() == user - - -class TestUserRedirectView: - def test_get_redirect_url(self, user: User, rf: RequestFactory): - view = UserRedirectView() - request = rf.get("/fake-url") - request.user = user - - view.request = request - - assert view.get_redirect_url() == f"/users/{user.username}/" - - -class TestUserDetailView: - def test_authenticated(self, user: User, rf: RequestFactory): - request = rf.get("/fake-url/") - request.user = UserFactory() - - response = user_detail_view(request, username=user.username) - - assert response.status_code == 200 - - def test_not_authenticated(self, user: User, rf: RequestFactory): - request = rf.get("/fake-url/") - request.user = AnonymousUser() # type: ignore - - response = user_detail_view(request, username=user.username) - - assert response.status_code == 302 - assert response.url == "/accounts/login/?next=/fake-url/" - - def test_case_sensitivity(self, rf: RequestFactory): - request = rf.get("/fake-url/") - request.user = UserFactory(username="UserName") - - with pytest.raises(Http404): - user_detail_view(request, username="username") diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/types.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/types.py deleted file mode 100644 index c01fc8e9..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/types.py +++ /dev/null @@ -1,19 +0,0 @@ -import strawberry -import strawberry_django -from django.contrib.auth import get_user_model - -User = get_user_model() - - -@strawberry_django.type(User) -class UserType: - """ - User type - """ - - id: strawberry.auto - username: strawberry.auto - name: strawberry.auto - email: strawberry.auto - is_staff: strawberry.auto - is_active: strawberry.auto diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/urls.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/urls.py deleted file mode 100644 index 8c8c7e2e..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/urls.py +++ /dev/null @@ -1,14 +0,0 @@ -from django.urls import path - -from {{ cookiecutter.project_slug }}.users.views import ( - user_detail_view, - user_redirect_view, - user_update_view, -) - -app_name = "users" -urlpatterns = [ - path("~redirect/", view=user_redirect_view, name="redirect"), - path("~update/", view=user_update_view, name="update"), - path("<str:username>/", view=user_detail_view, name="detail"), -] diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/views.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/views.py deleted file mode 100644 index 4a6e3973..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/users/views.py +++ /dev/null @@ -1,47 +0,0 @@ -from django.contrib import messages -from django.contrib.auth import get_user_model -from django.contrib.auth.mixins import LoginRequiredMixin -from django.urls import reverse -from django.utils.translation import gettext_lazy as _ -from django.views.generic import DetailView, RedirectView, UpdateView - -User = get_user_model() - - -class UserDetailView(LoginRequiredMixin, DetailView): - model = User - slug_field = "username" - slug_url_kwarg = "username" - - -user_detail_view = UserDetailView.as_view() - - -class UserUpdateView(LoginRequiredMixin, UpdateView): - model = User - fields = ["name"] - - def get_success_url(self): - return reverse("users:detail", kwargs={"username": self.request.user.username}) - - def get_object(self): - return User.objects.get(username=self.request.user.username) - - def form_valid(self, form): - messages.add_message( - self.request, messages.INFO, _("Infos successfully updated") - ) - return super().form_valid(form) - - -user_update_view = UserUpdateView.as_view() - - -class UserRedirectView(LoginRequiredMixin, RedirectView): - permanent = False - - def get_redirect_url(self): - return reverse("users:detail", kwargs={"username": self.request.user.username}) - - -user_redirect_view = UserRedirectView.as_view() diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/__init__.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/cloud_storage.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/cloud_storage.py deleted file mode 100644 index e9c01d62..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/cloud_storage.py +++ /dev/null @@ -1,10 +0,0 @@ -from storages.backends.s3boto3 import S3Boto3Storage - - -class S3StaticStorage(S3Boto3Storage): - location = "static" - - -class S3MediaStorage(S3Boto3Storage): - location = "media" - file_overwrite = False diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/context_processors.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/context_processors.py deleted file mode 100644 index de405076..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/context_processors.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.conf import settings - - -def settings_context(_request): - return {"settings": settings} diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/debugger.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/debugger.py deleted file mode 100644 index 99ae6d05..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/debugger.py +++ /dev/null @@ -1,34 +0,0 @@ -import logging -import os -import sys - -logger = logging.getLogger(__name__) - - -def debugger_connect_pycharm(host_ip): - logger.info("Pycharm pydevd connecting...") - import pydevd_pycharm - try: - pydevd_pycharm.settrace(host_ip, port=6400, stdoutToServer=True, stderrToServer=True) - except ConnectionRefusedError: - msg = "Debugger connection failed. Check IDE debugger is running and try again. Continuing without debugger." - logger.error(msg.upper()) - - -def debugger_connect_vscode(): - raise NotImplementedError("VSCode debugger not implemented") - - -def connect_debugger(): - host_ip = "host.docker.internal" - ide = os.getenv("DEBUGGER_IDE", None) - if host_ip and ide: - debuggers = { - "pycharm": debugger_connect_pycharm, - # "vscode": debugger_connect_vscode - } - try: - debuggers[ide](host_ip) - except KeyError: - logger.error(f"IDE {ide} not supported, must be one of {debuggers.keys()}") - sys.exit(1) diff --git a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/healthcheck.py b/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/healthcheck.py deleted file mode 100644 index 540914c6..00000000 --- a/{{cookiecutter.project_slug}}/backend/{{cookiecutter.project_slug}}/utils/healthcheck.py +++ /dev/null @@ -1,67 +0,0 @@ -import logging - -from django.http import HttpResponse, HttpResponseServerError - -logger = logging.getLogger("healthz") - - -class HealthCheckMiddleware(object): - def __init__(self, get_response): - self.get_response = get_response - # One-time configuration and initialization. - - def __call__(self, request): - if request.method == "GET": - if request.path == "/readiness": - return self.readiness(request) - elif request.path == "/healthz": - return self.healthz(request) - return self.get_response(request) - - def healthz(self, request): - """ - Returns that the server is alive. - """ - return HttpResponse("OK") - - def readiness(self, request): - # Connect to each database and do a generic standard SQL query - # that doesn't write any data and doesn't depend on any tables - # being present. - from django.db import connections - - for name in connections: - cursor = None - connection = connections[name] - try: - cursor = connection.cursor() - cursor.execute("SELECT 1;") - row = cursor.fetchone() - if row is None: - return HttpResponseServerError("db: invalid response") - except Exception as e: - logger.exception(e) - return HttpResponseServerError("db: cannot connect to database.") - finally: - if cursor: - cursor.close() - connection.close() - - # Call get_stats() to connect to each memcached instance and get its stats. - # This can effectively check if each is online. - try: - from django.core.cache import caches - from django.core.cache.backends.memcached import BaseMemcachedCache - - for cache in caches.all(): - if isinstance(cache, BaseMemcachedCache): - stats = cache._cache.get_stats() - if len(stats) != len(cache._servers): - return HttpResponseServerError( - "cache: cannot connect to cache." - ) - except Exception as e: - logger.exception(e) - return HttpResponseServerError("cache: cannot connect to cache.") - - return HttpResponse("OK") diff --git a/{{cookiecutter.project_slug}}/bitbucket-pipelines.yml b/{{cookiecutter.project_slug}}/bitbucket-pipelines.yml deleted file mode 100644 index 678c9565..00000000 --- a/{{cookiecutter.project_slug}}/bitbucket-pipelines.yml +++ /dev/null @@ -1,69 +0,0 @@ -image: python:3.12 - -definitions: - services: - docker: - memory: 3072 - - postgres: - image: postgres:16 - environment: - POSTGRES_DB: {{ cookiecutter.project_slug }} - POSTGRES_USER: {{ cookiecutter.project_slug }} - POSTGRES_PASSWORD: TESTPASSWORD -{% if cookiecutter.use_celery == 'y' %} - redis: - image: redis:stable -{% endif %} - - steps: - - step: &backend-tests - name: Backend Tests - caches: - - pip - script: - - export DATABASE_URL=postgres://{{ cookiecutter.project_slug }}:TESTPASSWORD@localhost:5432/{{ cookiecutter.project_slug }} -{% if cookiecutter.use_celery == 'y' %} - - export CELERY_BROKER_URL=redis://127.0.0.1:6379/0 -{% endif %} - - CI=true make backend-test - - services: -{% if cookiecutter.use_celery == 'y' %} - - redis -{% endif %} - - postgres - - - step: &check-lint-and-formatting - name: Check lint and formatting - caches: - - pip - script: - - make check-lint-and-formatting - -{% if cookiecutter.create_nextjs_frontend == 'y' %} - - step: &check-lint-and-test-frontend - name: Frontend Lint & Typecheck & Test - image: node:20 - caches: - - node - script: - - make check-lint-and-test-frontend - - - step: &check-test-frontend - name: Frontend Unit Tests - image: node:20 - caches: - - node - script: - - CI=true make frontend-test -{% endif %} - -pipelines: - default: - - parallel: - - step: *check-lint-and-formatting -{% if cookiecutter.create_nextjs_frontend == 'y' %} - - step: *check-lint-and-test-frontend -{% endif %} - - step: *backend-tests diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/.gitignore b/{{cookiecutter.project_slug}}/bootstrap-cluster/.gitignore deleted file mode 100644 index fe7a98fb..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -!sandbox/.env -!staging/.env -!prod/.env -!.env -controlplane.yaml -kubeconfig -talosconfig -worker.yaml -id_ed25519 -*_ips.txt -*.bak.* diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/README.md b/{{cookiecutter.project_slug}}/bootstrap-cluster/README.md deleted file mode 100644 index 084d143c..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/README.md +++ /dev/null @@ -1,288 +0,0 @@ -{%- if cookiecutter.operating_system == "talos" %}# Bootstrap Talos and ArgoCD - -After deploying infrastructure using Terraform, we can proceed with configuring -Talos and bootstrapping ArgoCD. - -Terraform is solely utilized for deploying infrastructure. Any subsequent -configuration of Talos or ArgoCD is done using Taskfile tasks. -{%- elif cookiecutter.operating_system == "k3s" %}# Bootstrap k3s and ArgoCD - -After deploying infrastructure using Terraform, we can proceed with configuring -k3s and bootstrapping ArgoCD. - -Terraform is solely utilized for deploying infrastructure. Any subsequent -configuration of k3s or ArgoCD is done using Taskfile tasks. -{%- endif %} - -To view a list of tasks and their descriptions, navigate to the -`bootstrap-cluster` directory and execute `task`. - -Note that there is a directory for each environment: sandbox, staging, and -cluster. - -We recommend opening the AWS serial console for each ec2 instance to monitor the -bootstrap process. - -{%- if cookiecutter.operating_system == "talos" %} - -### Bootstrapping Talos - -{%- elif cookiecutter.operating_system == "k3s" %} - -### Bootstrapping k3s - -{%- endif %} - -1. Navigate to the directory corresponding to the environment being set up and - run: - - ```shell - export ENV=sandbox - cd $ENV - ``` - -2. Review the `.env` file for the given environment: - - ```shell - CONTROL_PLANE_ENDPOINT: "https://k8s.sandbox.{{ cookiecutter.domain_name }}:6443" - CLUSTER_NAME: "{{ cookiecutter.project_dash }}-sandbox" - ``` - -{%- if cookiecutter.operating_system == "talos" %} - Note that we use a Talos factory image. This image contains a system - extension that provides the ECR credential provider. - - ``` - siderolabs/ecr-credential-provider (v1.28.1) - - This system extension provides a binary which implements Kubelet's - CredentialProvider API to authenticate against AWS' Elastic Container - Registry and pull images. - ``` -{%- endif %} -{%- if cookiecutter.operating_system == "talos" %} -3. Bootstrap Talos with the following command: - - ``` - task talos:bootstrap - ``` - - To understand what this task will do, examine the Taskfile configuration: - - ```yaml - bootstrap: - desc: | - Run all tasks required to bootstrap the Talos and Kubernetes cluster. - requires: - vars: [ENV] - cmds: - - task: generate_configs - - task: set_node_ips - - task: store_controlplane_config - - task: store_talosconfig - - task: apply_talos_config - - sleep 30 - - task: bootstrap_kubernetes - - sleep 30 - - task: generate_kubeconfig - - task: store_kubeconfig - - task: upgrade_talos - - task: enable_ecr_credential_helper - ``` - - It takes a few minutes for the cluster nodes to register as etcd - members and synchronize. - -{%- elif cookiecutter.operating_system == "k3s" %} -3. Bootstrap k3s with the following command: - - ``` - task k3s:bootstrap - ``` - - To understand what this task will do, examine the Taskfile configuration: - - ```yaml - bootstrap: - desc: | - Run all tasks required to bootstrap k3s and Kubernetes cluster. - requires: - vars: [ENV] - cmds: - - task: save-node-ips - - task: setup-ssh-key - - task: install-k3s - - task: fetch-kubeconfig - - task: store-kubeconfig - - task: enable-ecr-credential-helper - ``` - - It takes a few minutes for the cluster nodes to register as etcd - members and synchronize. - -{%- endif %} - - If the cluster fails to bootstrap, refer to the Troubleshooting section - below. - -{%- if cookiecutter.operating_system == "talos" %} -4. Verify the health of your cluster with: - - ```shell - task talos:health - ``` - - 5. Test kubectl access: - - ```shell - eval $(task talos:kubeconfig) - kubectl cluster-info - ``` -{%- elif cookiecutter.operating_system == "k3s" %} - -4. Test kubectl access: - - ```shell - eval $(task k3s:kubeconfig) - kubectl cluster-info - ``` -{%- endif %} - - This should return output similar to the following: - - ```shell - $ kubectl cluster-info - Kubernetes control plane is running at https://k8s.sandbox.{{ cookiecutter.domain_name }}:6443 - CoreDNS is running at https://k8s.sandbox.{{ cookiecutter.domain_name }}:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy - - To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. - ``` - -### Bootstrapping ArgoCD - -1. Review the branches used for deployment to the sandbox, staging and - production environments. The default configuration will release the `develop` - branch to the Sandbox and the `main` branch to the Production environment. - Make sure to make the `develop` branch the default branch for PRs on a newly - created Git repository. - - Review the branch rule in `bootstrap_root_app` job in - `bootstrap-cluster/argocd.yaml`: - - ``` - vars: - BRANCH: - sh: ([ "$ENV" = "production" ] && echo "main" || echo "develop") - ``` - - Review the `targetRevision` in the `kustomization.yaml` files shown below: - - `argocd/sandbox/apps/kustomization.yaml`: - - ``` - patches: - - patch: |- - - op: replace - path: /spec/source/targetRevision - value: develop - target: - kind: Application - name: ingress - ... - - patch: |- - - op: replace - path: /spec/source/targetRevision - value: develop - target: - kind: Application - name: {{ cookiecutter.project_slug }}-prod - ``` - - `argocd/prod/apps/kustomization.yaml`: - - ``` - patches: - - patch: |- - - op: replace - path: /spec/source/targetRevision - value: main - target: - kind: Application - name: ingress - ``` - -2. Next, we need to create a GitHub deploy key to allow ArgoCD to monitor the - repo. This step requires access to the 1password vault for your project. - - Review the vault name in the `op` cli command in - `bootstrap-cluster/argocd.yaml`: - - ``` - - op item create - ... - --vault='{{ cookiecutter.project_name }}' - ``` - - Sign into 1password with `op signin` and generate the deploy key: - - ```shell - task argocd:generate_github_deploy_key - ``` - -3. Add the deploy key to your Git repository - -4. Proceed with installing ArgoCD by executing: - - ```shell - task argocd:bootstrap - ``` - -The `argocd:bootstrap` task configuration is as follows: - -``` - bootstrap: - desc: Setup ArgoCD - cmds: - - task: install - - task: create_repo_credentials_secret - - task: bootstrap_root_app -``` - -5. ArgoCD will install the Sealed Secrets operator in the cluster. Once it is - installed, we can generate secrets for the given environment. - - ```shell - cd .. - make debug-$ENV-secrets - make $ENV-secrets - ``` - -6. Commit the `secrets.yaml` file for the given environment and push it to the - repo. - -## Troubleshooting - -{%- if cookiecutter.operating_system == "talos" %} -If bootstrapping Talos fails, we recommend resetting the config files and -recreating ec2 instances before trying again. - -1. Reset config and state with `task talos:reset_config` for the given - environment. - -2. Destroy and recreate ec2 instances: - - cd ../terraform/$ENV/ - terraform destroy \ - -target "module.cluster.module.control_plane_nodes[0].aws_instance.this[0]" \ - -target "module.c luster.module.control_plane_nodes[1].aws_instance.this[0]" \ - -target "module.c luster.module.control_plane_nodes[1].aws_instance.this[0]" - terraform plan -out="tfplan.out" - terraform apply tfplan.out -{%- elif cookiecutter.operating_system == "k3s" %} -If bootstrapping k3s fails, we recommend uninstalling k3s from each node and -boostrapping from scratch. - -```shell -task k3s:uninstall-k3s -``` -{%- endif %} diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/argocd.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/argocd.yaml deleted file mode 100644 index 6760a520..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/argocd.yaml +++ /dev/null @@ -1,80 +0,0 @@ -version: '3' - -env: - KUBECONFIG: ./{{ '{{.ENV}}' }}/kubeconfig - GITHUB_DEPLOY_KEY_TITLE: "{{ cookiecutter.project_name }} ArgoCD GitHub Deploy Key" - -tasks: - generate_github_deploy_key: - desc: | - Use the 1password CLI to generate a GitHub deploy key - requires: - vars: [ENV] - cmds: - - op item create - --category=ssh-key - --title='{{ '{{.GITHUB_DEPLOY_KEY_TITLE}}' }}' - --vault='{{ cookiecutter.project_name }}' - --ssh-generate-key ed25519 - - bootstrap: - desc: Setup ArgoCD - cmds: - - task: install - - task: create_repo_credentials_secret - - task: bootstrap_root_app - - install: - desc: Deploy ArgoCD using Helm - cmds: - - helm install argocd argo-cd - --repo https://argoproj.github.io/argo-helm - --version {{ '{{.ARGOCD_VERSION}}' }} - --namespace argocd - --create-namespace - --set configs.params.server.insecure=true - - create_repo_credentials_secret: - requires: - vars: [ENV] - vars: - GITHUB_DEPLOY_KEY_B64: - sh: op read "op://{{ cookiecutter.project_name }}/{{ '{{.GITHUB_DEPLOY_KEY_TITLE}}' }}/private key?ssh-format=openssh" | base64 -w0 - desc: Create and apply repo credentials secret for each repo - cmds: - - | - cat <<EOF | kubectl apply -f - - apiVersion: v1 - kind: Secret - metadata: - name: {{ '{{printf "%s-repocreds" .REPO_NAME}}' }} - namespace: argocd - labels: - argocd.argoproj.io/secret-type: repository - data: - type: {{ '{{"git" | b64enc}}' }} - url: {{ '{{.REPO_URL | b64enc}}' }} - sshPrivateKey: {{ '{{.GITHUB_DEPLOY_KEY_B64}}' }} - EOF - - create_github_webhook_secret: - requires: - vars: [ARGOCD_GITHUB_ACCESS_TOKEN] - desc: | - Create GitHub webhook secret and apply - - Usage: ARGOCD_GITHUB_ACCESS_TOKEN="secret token" task argocd:create_github_webhook_secret - cmds: - - kubectl -n argocd create secret generic github-token - --from-literal=token="{{ '{{ARGOCD_GITHUB_ACCESS_TOKEN}}' }}" - --dry-run=client -o yaml | kubectl apply -f - - - bootstrap_root_app: - requires: - vars: [ENV] - vars: - BRANCH: - sh: ([ "$ENV" = "production" ] && echo "main" || echo "develop") - desc: Bootstrap the Cluster - cmds: - - cat root-app.template.yaml | envsubst | kubectl apply -f - diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-control-plane.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-control-plane.yaml deleted file mode 100644 index 349aad1e..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-control-plane.yaml +++ /dev/null @@ -1,10 +0,0 @@ -cluster: - # Allow scheduling work loads on the control plane since we don't have a - # separate control plane - allowSchedulingOnControlPlanes: true - - # Install Kubelet Serving Certificate Approver and metrics-server during - # bootstrap - extraManifests: - - "https://raw.githubusercontent.com/alex1989hu/kubelet-serving-cert-approver/main/deploy/standalone-install.yaml" - - "https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml" diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-ecr-credential-helper.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-ecr-credential-helper.yaml deleted file mode 100644 index aafe1506..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-ecr-credential-helper.yaml +++ /dev/null @@ -1,15 +0,0 @@ -machine: - kubelet: - credentialProviderConfig: - apiVersion: 'kubelet.config.k8s.io/v1' - kind: 'CredentialProviderConfig' - providers: - - name: 'ecr-credential-provider' - matchImages: - - '*.dkr.ecr.*.amazonaws.com' - - '*.dkr.ecr.*.amazonaws.com.cn' - - '*.dkr.ecr-fips.*.amazonaws.com' - - '*.dkr.ecr.us-iso-east-1.c2s.ic.gov' - - '*.dkr.ecr.us-isob-east-1.sc2s.sgov.gov' - defaultCacheDuration: '12h' - apiVersion: 'credentialprovider.kubelet.k8s.io/v1' diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-machine.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-machine.yaml deleted file mode 100644 index 33f21e3c..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/patches/patch-machine.yaml +++ /dev/null @@ -1,8 +0,0 @@ -machine: - kubelet: - # The registerWithFQDN field is used to force kubelet to use the node - # FQDN for registration. This is required in clouds like AWS. - registerWithFQDN: true - # # Required for Metrics Server - extraArgs: - rotate-server-certificates: true diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/prod/.env b/{{cookiecutter.project_slug}}/bootstrap-cluster/prod/.env deleted file mode 100644 index e482b319..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/prod/.env +++ /dev/null @@ -1,2 +0,0 @@ -CONTROL_PLANE_ENDPOINT: "https://k8s.{{ cookiecutter.domain_name }}:6443" -CLUSTER_NAME: "{{ cookiecutter.project_dash }}-prod" diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/root-app.template.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/root-app.template.yaml deleted file mode 100644 index e69556e6..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/root-app.template.yaml +++ /dev/null @@ -1,27 +0,0 @@ ---- -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: root - namespace: argocd - creationTimestamp: null - finalizers: - - resources-finalizer.argocd.argoproj.io - labels: - app.kubernetes.io/name: root -spec: - destination: - namespace: argocd - server: https://kubernetes.default.svc - project: default - source: - path: argocd/${ENV}/apps - repoURL: {{ cookiecutter.repo_url }} - targetRevision: ${BRANCH} - syncPolicy: - automated: - allowEmpty: true - prune: true - selfHeal: true - syncOptions: - - allowEmpty=true diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/sandbox/.env b/{{cookiecutter.project_slug}}/bootstrap-cluster/sandbox/.env deleted file mode 100644 index e1ff4d2c..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/sandbox/.env +++ /dev/null @@ -1,2 +0,0 @@ -CONTROL_PLANE_ENDPOINT: "https://k8s.sandbox.{{ cookiecutter.domain_name }}:6443" -CLUSTER_NAME: "{{ cookiecutter.project_dash }}-sandbox" diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/staging/.env b/{{cookiecutter.project_slug}}/bootstrap-cluster/staging/.env deleted file mode 100644 index a02c79ec..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/staging/.env +++ /dev/null @@ -1,2 +0,0 @@ -CONTROL_PLANE_ENDPOINT: "https://k8s.staging.{{ cookiecutter.domain_name }}:6443" -CLUSTER_NAME: "{{ cookiecutter.project_dash }}-staging" diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/talos.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/talos.yaml deleted file mode 100644 index a7df944a..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/talos.yaml +++ /dev/null @@ -1,202 +0,0 @@ -version: '3' -env: - TALOSCONFIG: ./{{ '{{.ENV}}' }}/talosconfig - KUBECONFIG: ./{{ '{{.ENV}}' }}/kubeconfig -tasks: - bootstrap: - desc: | - Run all tasks required to bootstrap the Talos and Kubernetes cluster. - requires: - vars: [ENV] - cmds: - - task: generate_configs - - task: set_node_ips - - task: store_controlplane_config - - task: store_talosconfig - - task: apply_talos_config - - sleep 30 - - task: bootstrap_kubernetes - - sleep 30 - - task: generate_kubeconfig - - task: store_kubeconfig - - task: upgrade_talos - - task: enable_ecr_credential_helper - generate_configs: - desc: | - Generate the initial Talos configuration files for the control plane - and Talos nodes. - cmds: - - | - talosctl gen config {{ '{{.CLUSTER_NAME}}' }} {{ '{{.CONTROL_PLANE_ENDPOINT}}' }} \ - --output-types controlplane,talosconfig \ - --output ./{{ '{{.ENV}}' }}/ \ - --config-patch @patches/patch-machine.yaml \ - --config-patch-control-plane @patches/patch-control-plane.yaml \ - --with-examples=false \ - --with-docs=false - set_node_ips: - desc: | - Set the endpoints in the Talos configuration using the public IPs of - the control plane nodes from Terraform output. - vars: - EC2_HOSTS: - sh: | - tofu -chdir={{ '{{.TOFU_DIR}}' }}/{{ '{{.ENV}}' }} \ - output -raw control_plane_nodes_public_ips | tr ',' ' ' - requires: - vars: [ENV] - cmds: - - talosctl config endpoint {{ '{{.EC2_HOSTS}}' }} - apply_talos_config: - desc: | - Apply the Talos configuration to all nodes in the control plane. - cmds: - - | - for node in $(yq -r '.contexts[].endpoints[]' $TALOSCONFIG); do \ - echo "Applying config to $node" && \ - talosctl apply-config \ - --insecure \ - --nodes $node \ - --file ./{{ '{{.ENV}}' }}/controlplane.yaml; \ - done - bootstrap_kubernetes: - desc: | - Bootstrap the Kubernetes cluster on the first control plane node. - vars: - FIRST_NODE: - sh: yq -r '.contexts[].endpoints[0]' {{ '{{.ENV}}' }}/talosconfig - cmds: - - talosctl bootstrap --nodes {{ '{{.FIRST_NODE}}' }} - generate_kubeconfig: - desc: | - Generate the kubeconfig file to access the Kubernetes cluster using - Talos. - vars: - FIRST_NODE: - sh: yq -r '.contexts[].endpoints[0]' {{ '{{.ENV}}' }}/talosconfig - cmds: - - talosctl kubeconfig $KUBECONFIG --nodes {{ '{{.FIRST_NODE}}' }} --force - upgrade_talos: - desc: | - Upgrade Talos on all control plane nodes to a specified version. - cmds: - - task: health - - | - for node in $(yq -r '.contexts[].endpoints[]' $TALOSCONFIG); do - talosctl upgrade --nodes $node --image {{ '{{.TALOS_FACTORY_IMAGE}}' }}; \ - done - enable_ecr_credential_helper: - desc: | - Enable the ECR credential helper on all control plane nodes. - cmds: - - task: health - - | - for node in $(yq -r '.contexts[].endpoints[]' $TALOSCONFIG); do - talosctl patch mc \ - --nodes $node \ - --patch @patches/patch-ecr-credential-helper.yaml; \ - done - store_talosconfig: - desc: | - Store the Talos configuration file in AWS Secrets Manager. - requires: - vars: [ENV] - cmds: - - | - aws secretsmanager create-secret \ - --name "{{ '{{.ENV}}' }}_talosconfig_yaml" \ - --secret-string "$(base64 -w0 $TALOSCONFIG)" - store_controlplane_config: - desc: | - Store the Talos control plane configuration file in AWS Secrets - Manager. - requires: - vars: [ENV] - cmds: - - | - aws secretsmanager create-secret \ - --name "{{ '{{.ENV}}' }}_talos_controlplane_yaml" \ - --secret-string "$(base64 -w0 ./{{ '{{.ENV}}' }}/controlplane.yaml)" - store_kubeconfig: - desc: | - Store the Kubernetes kubeconfig file in AWS Secrets Manager. - requires: - vars: [ENV] - cmds: - - | - aws secretsmanager create-secret \ - --name "{{ '{{.ENV}}' }}_kubeconfig" \ - --secret-string "$(base64 -w0 $KUBECONFIG)" - health: - desc: | - Check the health of the Talos cluster. - vars: - FIRST_NODE: - sh: yq -r '.contexts[].endpoints[0]' {{ '{{.ENV}}' }}/talosconfig - cmds: - - talosctl health --nodes {{ '{{.FIRST_NODE}}' }} - services: - desc: | - Check service status on all notes. - cmds: - - | - for node in $(yq -r '.contexts[].endpoints[]' $TALOSCONFIG); do - talosctl service --nodes $node; - done - delete_all_secrets: - desc: | - Delete all related secrets from AWS Secrets Manager. - requires: - vars: [ENV] - cmds: - - | - aws secretsmanager delete-secret \ - --secret-id "{{ '{{.ENV}}' }}_kubeconfig" --force-delete-without-recovery - - | - aws secretsmanager delete-secret \ - --secret-id "{{ '{{.ENV}}' }}_talosconfig_yaml" --force-delete-without-recovery - - | - aws secretsmanager delete-secret \ - --secret-id "{{ '{{.ENV}}' }}_talos_controlplane_yaml" --force-delete-without-recovery - reset_config: - desc: | - Remove all config files and delete secrets in AWS Secrets Manager - requires: - vars: [ENV] - cmds: - - task: delete_all_secrets - - cd {{ '{{.ENV}}' }} && rm -f controlplane.yaml kubeconfig talosconfig - kubeconfig: - desc: | - Retrieve the Kubeconfig for a given cluster - - Since the commands run in sub-shell you can eval the output to export - KUBECONFIG to your current shell: - - eval $(task talos:kubeconfig) - silent: true - cmds: - - task: generate_kubeconfig - - echo "export KUBECONFIG=$(pwd)/{{ '{{.ENV}}' }}/kubeconfig" - fetch_config: - desc: | - Fetch kubeconfig, talosconfig and controlplane.yaml from AWS Secrets - Manager. - requires: - vars: [ENV] - cmds: - - | - aws secretsmanager get-secret-value \ - --secret-id "{{ '{{.ENV}}' }}_kubeconfig" | \ - yq ".SecretString" | tr -d '"' | \ - base64 -d > ./{{ '{{.ENV}}' }}/kubeconfig - - | - aws secretsmanager get-secret-value \ - --secret-id "{{ '{{.ENV}}' }}_talosconfig_yaml" | \ - yq ".SecretString" | tr -d '"' | \ - base64 -d > ./{{ '{{.ENV}}' }}/talosconfig - - | - aws secretsmanager get-secret-value \ - --secret-id "{{ '{{.ENV}}' }}_talos_controlplane_yaml" | \ - yq ".SecretString" | tr -d '"' | \ - base64 -d > ./{{ '{{.ENV}}' }}/controlplane.yaml diff --git a/{{cookiecutter.project_slug}}/bootstrap-cluster/taskfile.yaml b/{{cookiecutter.project_slug}}/bootstrap-cluster/taskfile.yaml deleted file mode 100644 index 6eb7ecd1..00000000 --- a/{{cookiecutter.project_slug}}/bootstrap-cluster/taskfile.yaml +++ /dev/null @@ -1,19 +0,0 @@ -version: '3' - -dotenv: ['.env', '{{ "{{.ENV}}" }}/.env'] - -includes: - argocd: ./argocd.yaml -{%- if cookiecutter.operating_system == "talos" %} - talos: ./talos.yaml -{%- elif cookiecutter.operating_system == "k3s" %} - k3s: ./k3s.yaml -{%- endif %} - -tasks: - default: - desc: | - List all available tasks in the Taskfile. - cmds: - - task --list - diff --git a/{{cookiecutter.project_slug}}/docs/README.md b/{{cookiecutter.project_slug}}/docs/README.md deleted file mode 100644 index f0f4c494..00000000 --- a/{{cookiecutter.project_slug}}/docs/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Project Documentation - -You are encouraged to add in this directory all documentation -useful for others (and you in future) to understand better -how the project work and to help developers to prepare their environment. - -Examples (not all possibilities) of good things that can be documented: - -- How to configure development environment using third-party -applications and integrations (e.g. Slack, Discord, external -APIs, etc); -- How to prepare the environment to accomplish a specific task -that demands business knowledge and populate data in multible tables; -- Glossary of business terms and actions that are not obvious -to the general public; -- Anything that you needed to research inside the project and -it could help a new developer not to have spent time on that research. diff --git a/{{cookiecutter.project_slug}}/docs/architecture.md b/{{cookiecutter.project_slug}}/docs/architecture.md deleted file mode 100644 index 8660d8e0..00000000 --- a/{{cookiecutter.project_slug}}/docs/architecture.md +++ /dev/null @@ -1,3 +0,0 @@ -# :house: Architecture - -TODO: Use lots of diagrams to document the architecture of the project. diff --git a/{{cookiecutter.project_slug}}/docs/debug.md b/{{cookiecutter.project_slug}}/docs/debug.md deleted file mode 100644 index 2fa639ac..00000000 --- a/{{cookiecutter.project_slug}}/docs/debug.md +++ /dev/null @@ -1,30 +0,0 @@ -# :bug: How to debug the application - -The steps below describe how to set up interactive debugging with PyCharm. - -## PyCharm Debugging Setup -Update `k8s/base/app.configmap.yaml` with `data` field `DEBUGGER_IDE: "pycharm"` - -In PyCharm: - -1. Go to 'Run' in the toolbar -2. Click on 'Edit Configurations' -3. Click on '+' in the top left of the dialog -4. Select 'Python Debug Server' -5. Set the host to 0.0.0.0 and the port to 6400, and the name as you see fit. -6. Click 'Ok' - -## Debugging in development -Before the code you want to debug, add the following lines: - -```python -from {{ cookiecutter.project_slug }}.utils.debugger import connect_debugger -connect_debugger() -``` - -You can then set break points in your IDE and call the code as usual to hit them. - -When the debugger is first connected, you will see a screen pop up about mapping - Click 'auto-detect' path mapping settings and choose the file that matches [backend/{{ cookiecutter.project_slug }}/utils/debugger.py](/backend/{{ cookiecutter.project_slug }}/utils/debugger.py) - -## Troubleshooting -If the debugger is connected early on, such as in `manage.py`, standard django functionality such the admin interface may break. For that reason connecting in proximity to the code you want to test is recommended. diff --git a/{{cookiecutter.project_slug}}/docs/deployment.md b/{{cookiecutter.project_slug}}/docs/deployment.md deleted file mode 100644 index 27573e45..00000000 --- a/{{cookiecutter.project_slug}}/docs/deployment.md +++ /dev/null @@ -1,10 +0,0 @@ -# :package: How to deploy - -## Infrastructure provisioning - -Terraform can be used to provision AWS resources for your project deployment. -Read [terraform/README.md](/terraform/README.md) for more information and steps for provisioning resources. - -## Application deployment - -Use ArgoCD and Kubernetes to automate the deployment of your application to your infrastructure. ArgoCD monitors changes within your repository, promptly applying the relevant Kubernetes manifests. Read [bootstrap-cluster/README.md](/bootstrap-cluster/README.md) for more details. diff --git a/{{cookiecutter.project_slug}}/docs/development.md b/{{cookiecutter.project_slug}}/docs/development.md deleted file mode 100644 index c2bd65d3..00000000 --- a/{{cookiecutter.project_slug}}/docs/development.md +++ /dev/null @@ -1,71 +0,0 @@ -# :technologist: How to set up your local environment for development - -## Requirements - -To work with Kubernetes, you need to install some additional software packages. -Depending on your operating system, the installation instructions may vary. - -The documentation and scripts in the repo are written to work with `kubectl`, `kind` and `Tilt`. - -Consult the links below if you prefer to use Minikube or Docker Desktop instead: -* [minikube](https://minikube.sigs.k8s.io/docs/start/). -* [Docker](https://docs.docker.com/get-docker/). - -## Setup your environment - -1. Get the repository - - $ git clone {{ cookiecutter.repo_url }} - $ cd {{ cookiecutter.project_slug }} - -2. Prepare the environment variables. Edit the `.envrc` file to work for your environment. - -## Run the kubernetes cluster and the {{ cookiecutter.project_slug }} app to develop the code - -First load the environment variables, then run: - - $ make setup - $ tilt up - -:information_source: It may take a little bit of time for all the services to start up, and it's possible for -the first run to fail because of timing conflicts. If you do see messages indicating there -were errors during the first run, stop all the containers using Ctrl-C, and then try it again. - -You are now ready to edit the code. -The app will be automatically reloaded when its files change. - -To delete resources created by Tilt once you are done working: - - $ tilt down - -This will not delete persistent volumes created by Tilt, and you should be able to start Tilt again with your data intact. - -To remove the cluster entirely: - - $ kind delete cluster --name {{ cookiecutter.project_slug }} - -To switch between different Scaf project contexts: - - $ tilt down # inside the codebase of the previous project - $ make setup # inside the codebase of the project you want to work on - $ tilt up - -## Next steps - -Creating a superuser account in the backend is useful so you have access to -Django Admin that will be accessible at [http://localhost:8000/admin](http://localhost:8000/admin) - -To create a superuser use the following commands: - - $ make shell-backend - $ ./manage.py createsuperuser -{% if cookiecutter.create_nextjs_frontend == 'y' %} -This project has a NextJS frontend configured. You can access it at [http://localhost:3000/](http://localhost:3000/). -{% endif %} - -## Update dependencies - -To update the backend app dependencies, you must edit the `backend/requirements/*.in` files. -Once you have made your changes, you need to regenerate the `backend/requirements/*.txt` files using: - - $ make compile diff --git a/{{cookiecutter.project_slug}}/docs/monitoring.md b/{{cookiecutter.project_slug}}/docs/monitoring.md deleted file mode 100644 index d517b0ab..00000000 --- a/{{cookiecutter.project_slug}}/docs/monitoring.md +++ /dev/null @@ -1,91 +0,0 @@ -# :microscope: How to monitor the application -{% if cookiecutter.use_sentry == 'y' %} -### How to monitor errors - -Sentry can be used for error reporting at the application level. Sentry is included as a dependency in the project requirements, and the SENTRY_DSN configuration variable is included in the Django config map. -Next, one needs to add the project to Sentry by following the steps below: - -Note: The values for both tokens can be empty if you don't wish to use Sentry. - -1. Create two projects in your organisation's Sentry instance, e.g. https://sixfeetup.sentry.io/projects/ - 1. One project for the backend - 2. One project for the frontend -2. Configure Slack notifications -3. Add team members in Sentry -4. Update `k8s/base/app.configmap.yaml` `SENTRY_DSN_BACKEND`, `VITE_SENTRY_DSN_FRONTEND` with the DSNs appropriate for the relevant Sentry projects. - -For more detailed steps view [Sentry specific documentation](/docs/sentry.md) - -{% endif %} -### How to monitor logs and the deployed application - -Install Loki for log aggregation and the Kube Prometheus Stack with Grafana Dashboards for monitoring. - -#### Setup AWS credentials - -First export the credentials to your environment variables. Change the values accordingly: - -``` -export AWS_ACCESS_KEY_ID='ABC123456' -export AWS_SECRET_ACCESS_KEY='ABC123456' -``` - -Then create a secret in the monitoring namespace: - -``` -kubectl create secret generic iam-loki-s3 --from-literal=AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID --from-literal=AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY -n monitoring -``` - -#### Install monitoring - -Before installing the monitoring tools, you will need to export the GRAFANA_ADMIN_PASSWORD environment variable. This will be used to set the Grafana admin password. Change the value accordingly: - -``` -export GRAFANA_ADMIN_PASSWORD='ABC123456' -``` - -Now install the loki-stack and kube-prometheus-stack helm charts: - -``` -make monitoring-up -``` - -If you want to store the logs in an S3 bucket, you will need to include the yaml values `k8s/_monitoring/loki-stack-values.yaml` file for the `helm install loki` command in the Makefile: - -``` -helm install loki grafana/loki-stack --values k8s/_monitoring/loki-stack-values.yaml --namespace monitoring --create-namespace -``` - -#### Connect to Grafana dashboard - -You can connect to Grafana through local port forwarding using the steps below. Alternatively, you can set up ingress to point to Grafana. - -``` -make monitoring-port-forward -``` - -And open http://localhost:8080 on your browser - -Login with admin / prom-operator that are the default values. To see these values, run - -``` -make monitoring-login -``` - -Login to Grafana. Hit the `Explore` button and this gets you to the place with existing data sources. Select the newly added Loki data source. - -You are also able to change the password for the Grafana admin user. To do this, run the following command: - -``` -kubectl exec --namespace monitoring -c grafana -it $(kubectl get pods --namespace monitoring -l "app.kubernetes.io/name=grafana" -o jsonpath="{.items[0].metadata.name}") -- grafana-cli admin reset-admin-password newpassword -``` - -By default, you are on the code view, and you can hit the 'label browser' option on the left side and make a selection based on a number of items - eg select namespace and the namespace that interests you. Hit the `Live` mode on the right side of the screen to see logs in real time - a good check that things are setup as expected! - -#### Create a dashboard - -There is a predefined django logs table dashboard that can be created with the following command: - -``` -make monitoring-dashboard -``` diff --git a/{{cookiecutter.project_slug}}/docs/project-overview.md b/{{cookiecutter.project_slug}}/docs/project-overview.md deleted file mode 100644 index 6f6f43b8..00000000 --- a/{{cookiecutter.project_slug}}/docs/project-overview.md +++ /dev/null @@ -1,3 +0,0 @@ -# :telescope: Project overview - -TODO: Describe why this project is needed and what it's about diff --git a/{{cookiecutter.project_slug}}/docs/qa.md b/{{cookiecutter.project_slug}}/docs/qa.md deleted file mode 100644 index df3c397c..00000000 --- a/{{cookiecutter.project_slug}}/docs/qa.md +++ /dev/null @@ -1,3 +0,0 @@ -# :test_tube: How to test the application - -TODO: Document all the testing and QA processes. diff --git a/{{cookiecutter.project_slug}}/docs/secrets.md b/{{cookiecutter.project_slug}}/docs/secrets.md deleted file mode 100644 index e2b699a2..00000000 --- a/{{cookiecutter.project_slug}}/docs/secrets.md +++ /dev/null @@ -1,33 +0,0 @@ -# :shushing_face: How to manage passwords and sensitive values - -## Using SealedSecrets - -SealedSecrets can be used to encrypt passwords for the values to be safely checked in. -Creating a new secret involves encrypting the secret using kubeseal. [Installing kubeseal](https://github.com/bitnami-labs/sealed-secrets#kubeseal). - -Configure kubernetes to your current project config and context, making sure you are in the correct prod/sandbox environment - - $ export KUBECONFIG=~/.kube/config:~/.kube/{{ cookiecutter.project_slug }}.ec2.config - $ kubectl config use-context {{ cookiecutter.project_slug }}-ec2-cluster - -Add the secrets to your manifest using the secrets template file, and run kubeseal on the unencrypted values. The makefile target `sandbox-secrets` will replace the variables in `./k8s/templates/secrets.yaml.template` with the encoded variables from the environment, and copy the manifest with the encrypted values to `.k8s/overlays/sandbox/secrets.yaml`. The same can be done for the prod environment using the `prod-secrets` target - - $ make sandbox-secrets - - $ make prod-secrets - -The `k8s/*/secrets.yaml` file can now be safely checked in. The passwords will be unencrypted by SealedSecrets in the cluster. -When a secret is added/removed update the `k8s/templates` files, update the environment variables in .envrc and rerun the make commands. - -The decrypted values can be retrieved running: - - $ kubectl get secret secrets-config -n {{ cookiecutter.project_dash }} -o yaml > unsealed_secrets.yaml - -## Using .envrc file - -To ease managing your passwords and secrets you can store the values in 1Password. -You will need to install and configure [1Password cli](https://developer.1password.com/docs/cli/get-started/) - -You can automatically source from the `.envrc` file using [direnv](https://direnv.net/docs/installation.html) - -You can also manually export the variables to your environment using `source .envrc` diff --git a/{{cookiecutter.project_slug}}/docs/sentry.md b/{{cookiecutter.project_slug}}/docs/sentry.md deleted file mode 100644 index 454e83d1..00000000 --- a/{{cookiecutter.project_slug}}/docs/sentry.md +++ /dev/null @@ -1,51 +0,0 @@ -## Detailed steps for creating and configuring a project in Sentry - -### Create the Project in Sentry - -1. Log in to sentry.io and click the Create Project button -2. Choose Django -3. Name the Project with client-backend naming convention (ex. {{ cookiecutter.project_dash }}-backend) -4. Assign a team (create a team, if needed, with the plus icon next to the team dropdown). Teams should be based around the people involved in a project or projects that need to know about errors, not just the client. -5. Click the Create Project button -6. Repeat the above steps with the following changes: -7. Choose Next.js -8. Name the Project with client-frontend naming convention (ex. {{ cookiecutter.project_dash }}-frontend) -9. Assign a team (create a team, if needed, with the plus icon next to the team dropdown). Teams should be based around the people involved in a project or projects that need to know about errors, not just the client. -10. Click the Create Project button - -### Configure Slack Notifications - -1. Click on Setting on the sidebar -2. Click on Projects on the secondary sidebar that is revealed -3. Click on the Project created in the previous section -4. Click on Alerts on the new secondary sidebar -5. Edit the existing rule or Add a new rule if there is not one already -6. Use “Send a notification for new issues” for the Rule Name -7. Choose “An issue is first seen” for the Conditions -8. Leave “All Environments” -9. Delete the “Send a notification (for all legacy integrations)” Action, if it exists, to disable sending emails -10. Add an Action and choose “Send a notification to the Slack workspace” option from the menu and fill in the appropriate `#channel` name - -### Add Team Members -1. Click Settings on the sidebar -2. Click Teams on the secondary sidebar that is revealed -3. Click on the Team assigned to the Project you just created -4. Click Add Member to add additional team members as needed for the project - -### Add code to Django - -By default this is in the base config. Make sure the following is to your preferences in all logical locations in the `backend/config/settings/{environment}.py` files: - -``` - import sentry_sdk - ... - sentry_sdk.init( - dsn=env.str("SENTRY_DSN_BACKEND", default=""), - environment=env.str("ENVIRONMENT", default="production"), - release=env.str("RELEASE", default="dev"), - ) -``` - -Update `k8s/base/app.configmap.yaml` `SENTRY_DSN_BACKEND`, `VITE_SENTRY_DSN_FRONTEND` with the DSNs provided for the relevant Sentry projects. - -You can find them in Sentry by clicking Settings on the sidebar, then Projects on the secondary sidebar, then the project, then Client Keys (DSN) diff --git a/{{cookiecutter.project_slug}}/frontend/.dockerignore b/{{cookiecutter.project_slug}}/frontend/.dockerignore deleted file mode 100644 index 603d1488..00000000 --- a/{{cookiecutter.project_slug}}/frontend/.dockerignore +++ /dev/null @@ -1,11 +0,0 @@ -# Items that don't need to be in a Docker image. -# Anything not used by the build system should go here. -Dockerfile -.dockerignore -.gitignore -README.md - -# Artifacts that will be built during image creation. -# This should contain all files created during `npm run build`. -*/build -*/node_modules diff --git a/{{cookiecutter.project_slug}}/frontend/.env.local.example b/{{cookiecutter.project_slug}}/frontend/.env.local.example deleted file mode 100644 index 69cba1a1..00000000 --- a/{{cookiecutter.project_slug}}/frontend/.env.local.example +++ /dev/null @@ -1,3 +0,0 @@ -IS_PRE_PUSH_HOOKS_ENABLED=true -NEXT_PUBLIC_GRAPHQL_ENDPOINT=http://localhost:8000/graphql/ -NEXT_GRAPHQL_ENDPOINT=http://backend:8000/graphql/ diff --git a/{{cookiecutter.project_slug}}/frontend/.eslintrc.json b/{{cookiecutter.project_slug}}/frontend/.eslintrc.json deleted file mode 100644 index 6ac87541..00000000 --- a/{{cookiecutter.project_slug}}/frontend/.eslintrc.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "extends": [ - "next/core-web-vitals", - "plugin:@typescript-eslint/recommended", - "plugin:jsx-a11y/recommended", - "plugin:react-hooks/recommended", - "eslint:recommended", - "plugin:react/recommended", - "plugin:react/jsx-runtime" - ], - "plugins": ["jsx-a11y", "unused-imports"], - "rules": { - "react/jsx-curly-brace-presence": "error", - "@typescript-eslint/no-unused-vars": "off", - "unused-imports/no-unused-imports": "error", - "unused-imports/no-unused-vars": [ - "warn", - { - "vars": "all", - "varsIgnorePattern": "^_", - "args": "after-used", - "argsIgnorePattern": "^_" - } - ], - "@typescript-eslint/no-unnecessary-condition": "error", - "import/order": [ - "error", - { - "alphabetize": { - "caseInsensitive": true, - "order": "asc" - }, - "groups": ["external", "builtin", "internal", "parent", "sibling", "index"], - "newlines-between": "always" - } - ], - "object-shorthand": ["error", "properties"], - "react/jsx-no-useless-fragment": "error", - "require-await": "error", - // disallow specific imports - "no-restricted-imports": [ - "error", - { - "paths": [ - { - "name": "@apollo/client", - "importNames": ["gql"], - "message": "Use the @/__generated__/gql to get proper typings!" - }, - { - "name": "@apollo/client/core", - "importNames": ["gql"], - "message": "Use the @/__generated__/gql to get proper typings!" - }, - { - "name": "@testing-library/react", - "importNames": ["*"], - "message": "Use the imports from test-utils instead!" - } - ] - } - ] - }, - "parserOptions": { - "project": ["./tsconfig.json"] - } -} diff --git a/{{cookiecutter.project_slug}}/frontend/.gitignore b/{{cookiecutter.project_slug}}/frontend/.gitignore deleted file mode 100644 index 4ce22568..00000000 --- a/{{cookiecutter.project_slug}}/frontend/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local -.env - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts -!lib/ diff --git a/{{cookiecutter.project_slug}}/frontend/.husky/pre-push b/{{cookiecutter.project_slug}}/frontend/.husky/pre-push deleted file mode 100644 index d3b14bcc..00000000 --- a/{{cookiecutter.project_slug}}/frontend/.husky/pre-push +++ /dev/null @@ -1,9 +0,0 @@ -cd frontend -if test -f ./.env.local; then - source ./.env.local - if [ "$IS_PRE_PUSH_HOOKS_ENABLED" = "true" ] || [ "$IS_PRE_PUSH_HOOKS_ENABLED" = "1" ]; then - npm run format-check - npm run lint-src - npm run typecheck - fi -fi diff --git a/{{cookiecutter.project_slug}}/frontend/.prettierignore b/{{cookiecutter.project_slug}}/frontend/.prettierignore deleted file mode 100644 index be956f34..00000000 --- a/{{cookiecutter.project_slug}}/frontend/.prettierignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -.next -out -public -__generated__ \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/frontend/.prettierrc b/{{cookiecutter.project_slug}}/frontend/.prettierrc deleted file mode 100644 index 8992f03d..00000000 --- a/{{cookiecutter.project_slug}}/frontend/.prettierrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "arrowParens": "avoid", - "bracketSpacing": true, - "jsxSingleQuote": true, - "printWidth": 120, - "quoteProps": "as-needed", - "semi": false, - "singleQuote": true, - "tabWidth": 2, - "trailingComma": "none", - "plugins": ["prettier-plugin-tailwindcss"], - "tailwindFunctions": ["clsx"] -} diff --git a/{{cookiecutter.project_slug}}/frontend/Dockerfile b/{{cookiecutter.project_slug}}/frontend/Dockerfile deleted file mode 100644 index 7a68bfe9..00000000 --- a/{{cookiecutter.project_slug}}/frontend/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM node:iron as base -FROM base AS build - -WORKDIR /app -COPY package*.json ./ -RUN npm install - -# copy node_modules from the build image -FROM base - -WORKDIR /app -RUN chown node:node /app -COPY --from=build --chown=node:node /app/node_modules node_modules -COPY --chown=node:node . /app -USER node - -CMD ["npm", "run", "dev"] diff --git a/{{cookiecutter.project_slug}}/frontend/README.md b/{{cookiecutter.project_slug}}/frontend/README.md deleted file mode 100644 index 23a47c96..00000000 --- a/{{cookiecutter.project_slug}}/frontend/README.md +++ /dev/null @@ -1,39 +0,0 @@ -This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). - -## Getting Started - -Running the development server: - -Tilt will automatically deploy a NextJS container for development, and it is recommended not to run NextJS locally. - -Update the .env.local.example file to .env.local -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. - -You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. -This project uses GraphQL for the backend, and Apollo Client for the frontend. The Apollo Client is set up in the `lib/apolloClient.ts` file. - -## Environment Variables - -| Variable Name | Explanation | -| ---------------------------- | ---------------------------------------------------------- | --- | -| IS_PRE_PUSH_HOOKS_ENABLED | Controls husky pre-push hooks for frontend folder | | -| NEXT_PUBLIC_GRAPHQL_ENDPOINT | The public graphql endpoint url | -| NEXT_GRAPHQL_ENDPOINT | The graphql endpoint url to be used for serverside queries | | - -## Suggested Tools - -[Apollo Client Devtools](https://chromewebstore.google.com/detail/apollo-client-devtools/jdkknkkbebbapilgoeccciglkfbmbnfm) -[GraphQL Network Inspector](https://chromewebstore.google.com/detail/graphql-network-inspector/ndlbedplllcgconngcnfmkadhokfaaln) - -## Learn More - -To learn more about Next.js, take a look at the following resources: - -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. - -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -Check out the official [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/{{cookiecutter.project_slug}}/frontend/__generated__/fragment-masking.ts b/{{cookiecutter.project_slug}}/frontend/__generated__/fragment-masking.ts deleted file mode 100644 index aca71b13..00000000 --- a/{{cookiecutter.project_slug}}/frontend/__generated__/fragment-masking.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable */ -import { ResultOf, DocumentTypeDecoration, TypedDocumentNode } from '@graphql-typed-document-node/core'; -import { FragmentDefinitionNode } from 'graphql'; -import { Incremental } from './graphql'; - - -export type FragmentType<TDocumentType extends DocumentTypeDecoration<any, any>> = TDocumentType extends DocumentTypeDecoration< - infer TType, - any -> - ? [TType] extends [{ ' $fragmentName'?: infer TKey }] - ? TKey extends string - ? { ' $fragmentRefs'?: { [key in TKey]: TType } } - : never - : never - : never; - -// return non-nullable if `fragmentType` is non-nullable -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> -): TType; -// return nullable if `fragmentType` is undefined -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | undefined -): TType | undefined; -// return nullable if `fragmentType` is nullable -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null -): TType | null; -// return nullable if `fragmentType` is nullable or undefined -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | null | undefined -): TType | null | undefined; -// return array of non-nullable if `fragmentType` is array of non-nullable -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: Array<FragmentType<DocumentTypeDecoration<TType, any>>> -): Array<TType>; -// return array of nullable if `fragmentType` is array of nullable -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: Array<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined -): Array<TType> | null | undefined; -// return readonly array of non-nullable if `fragmentType` is array of non-nullable -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> -): ReadonlyArray<TType>; -// return readonly array of nullable if `fragmentType` is array of nullable -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined -): ReadonlyArray<TType> | null | undefined; -export function useFragment<TType>( - _documentNode: DocumentTypeDecoration<TType, any>, - fragmentType: FragmentType<DocumentTypeDecoration<TType, any>> | Array<FragmentType<DocumentTypeDecoration<TType, any>>> | ReadonlyArray<FragmentType<DocumentTypeDecoration<TType, any>>> | null | undefined -): TType | Array<TType> | ReadonlyArray<TType> | null | undefined { - return fragmentType as any; -} - - -export function makeFragmentData< - F extends DocumentTypeDecoration<any, any>, - FT extends ResultOf<F> ->(data: FT, _fragment: F): FragmentType<F> { - return data as FragmentType<F>; -} -export function isFragmentReady<TQuery, TFrag>( - queryNode: DocumentTypeDecoration<TQuery, any>, - fragmentNode: TypedDocumentNode<TFrag>, - data: FragmentType<TypedDocumentNode<Incremental<TFrag>, any>> | null | undefined -): data is FragmentType<typeof fragmentNode> { - const deferredFields = (queryNode as { __meta__?: { deferredFields: Record<string, (keyof TFrag)[]> } }).__meta__ - ?.deferredFields; - - if (!deferredFields) return true; - - const fragDef = fragmentNode.definitions[0] as FragmentDefinitionNode | undefined; - const fragName = fragDef?.name?.value; - - const fields = (fragName && deferredFields[fragName]) || []; - return fields.length > 0 && fields.every(field => data && field in data); -} diff --git a/{{cookiecutter.project_slug}}/frontend/__generated__/gql.ts b/{{cookiecutter.project_slug}}/frontend/__generated__/gql.ts deleted file mode 100644 index dbd15e57..00000000 --- a/{{cookiecutter.project_slug}}/frontend/__generated__/gql.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* eslint-disable */ -import * as types from './graphql'; -import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - -/** - * Map of all GraphQL operations in the project. - * - * This map has several performance disadvantages: - * 1. It is not tree-shakeable, so it will include all operations in the project. - * 2. It is not minifiable, so the string of a GraphQL query will be multiple times inside the bundle. - * 3. It does not support dead code elimination, so it will add unused operations. - * - * Therefore it is highly recommended to use the babel or swc plugin for production. - */ -const documents = { - "\n query Me {\n me {\n id\n name\n }\n }\n": types.MeDocument, -}; - -/** - * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - * - * - * @example - * ```ts - * const query = gql(`query GetUser($id: ID!) { user(id: $id) { name } }`); - * ``` - * - * The query argument is unknown! - * Please regenerate the types. - */ -export function gql(source: string): unknown; - -/** - * The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - */ -export function gql(source: "\n query Me {\n me {\n id\n name\n }\n }\n"): (typeof documents)["\n query Me {\n me {\n id\n name\n }\n }\n"]; - -export function gql(source: string) { - return (documents as any)[source] ?? {}; -} - -export type DocumentType<TDocumentNode extends DocumentNode<any, any>> = TDocumentNode extends DocumentNode< infer TType, any> ? TType : never; \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/frontend/__generated__/graphql.ts b/{{cookiecutter.project_slug}}/frontend/__generated__/graphql.ts deleted file mode 100644 index b0f85aa1..00000000 --- a/{{cookiecutter.project_slug}}/frontend/__generated__/graphql.ts +++ /dev/null @@ -1,111 +0,0 @@ -/* eslint-disable */ -import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe<T> = T | null; -export type InputMaybe<T> = Maybe<T>; -export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] }; -export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> }; -export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> }; -export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never }; -export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } -}; - -export type OperationInfo = { - __typename?: 'OperationInfo'; - /** List of messages returned by the operation. */ - messages: Array<OperationMessage>; -}; - -export type OperationMessage = { - __typename?: 'OperationMessage'; - /** The error code, or `null` if no error code was set. */ - code?: Maybe<Scalars['String']['output']>; - /** The field that caused the error, or `null` if it isn't associated with any particular field. */ - field?: Maybe<Scalars['String']['output']>; - /** The kind of this message. */ - kind: OperationMessageKind; - /** The error message. */ - message: Scalars['String']['output']; -}; - -export enum OperationMessageKind { - Error = 'ERROR', - Info = 'INFO', - Permission = 'PERMISSION', - Validation = 'VALIDATION', - Warning = 'WARNING' -} - -export type RegisterPayload = OperationInfo | UserType; - -export type UpdateUserPayload = OperationInfo | UserType; - -export type UserMutation = { - __typename?: 'UserMutation'; - login: UserType; - logout: Scalars['Boolean']['output']; - register: RegisterPayload; - updateUser: UpdateUserPayload; -}; - - -export type UserMutationLoginArgs = { - password: Scalars['String']['input']; - username: Scalars['String']['input']; -}; - - -export type UserMutationRegisterArgs = { - input: UserRegistrationInput; -}; - - -export type UserMutationUpdateUserArgs = { - input: UserPartialUpdateInput; -}; - -/** User(id, password, last_login, is_superuser, username, first_name, last_name, email, is_staff, is_active, date_joined, name) */ -export type UserPartialUpdateInput = { - id?: InputMaybe<Scalars['ID']['input']>; - name?: InputMaybe<Scalars['String']['input']>; -}; - -export type UserQuery = { - __typename?: 'UserQuery'; - me: UserType; -}; - -/** User(id, password, last_login, is_superuser, username, first_name, last_name, email, is_staff, is_active, date_joined, name) */ -export type UserRegistrationInput = { - password: Scalars['String']['input']; - /** Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only. */ - username: Scalars['String']['input']; -}; - -/** User(id, password, last_login, is_superuser, username, first_name, last_name, email, is_staff, is_active, date_joined, name) */ -export type UserType = { - __typename?: 'UserType'; - email: Scalars['String']['output']; - id: Scalars['ID']['output']; - /** Designates whether this user should be treated as active. Unselect this instead of deleting accounts. */ - isActive: Scalars['Boolean']['output']; - /** Designates whether the user can log into this admin site. */ - isStaff: Scalars['Boolean']['output']; - name: Scalars['String']['output']; - /** Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only. */ - username: Scalars['String']['output']; -}; - -export type MeQueryVariables = Exact<{ [key: string]: never; }>; - - -export type MeQuery = { __typename?: 'UserQuery', me: { __typename?: 'UserType', id: string, name: string } }; - - -export const MeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode<MeQuery, MeQueryVariables>; \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/frontend/__generated__/index.ts b/{{cookiecutter.project_slug}}/frontend/__generated__/index.ts deleted file mode 100644 index f5159916..00000000 --- a/{{cookiecutter.project_slug}}/frontend/__generated__/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./fragment-masking"; -export * from "./gql"; \ No newline at end of file diff --git a/{{cookiecutter.project_slug}}/frontend/__tests__/about.test.tsx b/{{cookiecutter.project_slug}}/frontend/__tests__/about.test.tsx deleted file mode 100644 index a07fb6c2..00000000 --- a/{{cookiecutter.project_slug}}/frontend/__tests__/about.test.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { expect, test } from 'vitest' -import AboutPage from '../pages/about' -import { GET_ME } from '@/pages' -import { render, screen } from '@/utils/test-utils' - -const mocks = [ - { - request: { - query: GET_ME - }, - result: { - data: { - me: { id: '1', name: 'John Doe' } - } - } - } -] - -test('AboutPage', async () => { - render(<AboutPage />, { mocks }) - expect(await screen.findByRole('heading', { level: 1, name: 'About Page' })).toBeInTheDocument() - expect(await screen.findByText('John Doe')).toBeInTheDocument() -}) diff --git a/{{cookiecutter.project_slug}}/frontend/codegen.ts b/{{cookiecutter.project_slug}}/frontend/codegen.ts deleted file mode 100644 index 431d76b2..00000000 --- a/{{cookiecutter.project_slug}}/frontend/codegen.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { CodegenConfig } from '@graphql-codegen/cli' - -const config: CodegenConfig = { - schema: 'http://localhost:8000/graphql/', - // this assumes that all your source files are in a top-level `src/` directory - you might need to adjust this to your file structure - documents: ['./**/*.{ts,tsx}'], - generates: { - './__generated__/': { - preset: 'client', - plugins: [], - presetConfig: { - gqlTagName: 'gql' - } - } - }, - ignoreNoDocuments: true -} - -export default config diff --git a/{{cookiecutter.project_slug}}/frontend/components/ErrorBoundary.tsx b/{{cookiecutter.project_slug}}/frontend/components/ErrorBoundary.tsx deleted file mode 100644 index 8a8aca05..00000000 --- a/{{cookiecutter.project_slug}}/frontend/components/ErrorBoundary.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Component, ErrorInfo, ReactNode } from 'react' - -interface Props { - children: ReactNode -} - -interface State { - hasError: boolean - error: Error | null - errorInfo: ErrorInfo | null -} - -class ErrorBoundary extends Component<Props, State> { - constructor(props: Props) { - super(props) - this.state = { hasError: false, error: null, errorInfo: null } - } - - static getDerivedStateFromError(error: Error): State { - // Update state so the next render will show the fallback UI. - return { hasError: true, error, errorInfo: null } - } - - componentDidCatch(error: Error, errorInfo: ErrorInfo) { - // You can also log the error to an error reporting service - this.setState({ error, errorInfo }) - console.error('ErrorBoundary caught an error', error, errorInfo) - } - - render() { - if (this.state.hasError) { - return ( - <div> - <h1>Something went wrong.</h1> - <details className='whitespace-nowrap'> - {this.state.error && this.state.error.toString()} - <br /> - {this.state.errorInfo?.componentStack} - </details> - </div> - ) - } - - return this.props.children - } -} - -export default ErrorBoundary diff --git a/{{cookiecutter.project_slug}}/frontend/components/Footer.tsx b/{{cookiecutter.project_slug}}/frontend/components/Footer.tsx deleted file mode 100644 index 3e09209b..00000000 --- a/{{cookiecutter.project_slug}}/frontend/components/Footer.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import Link from 'next/link' - -const Footer = () => { - return ( - <footer className='bg-gray-800 py-8 text-white'> - <div className='container mx-auto px-4'> - <div className='flex items-center justify-between'> - <div> - <h3 className='text-lg font-bold'>{'{{ cookiecutter.project_name }}'}</h3> - <p className='text-sm'> - © {new Date().getFullYear()} {'{{ cookiecutter.project_name }}'}. All rights reserved. - </p> - </div> - <div className='space-x-4'> - <Link href='/'>Home</Link> - <Link href='/about'>About</Link> - </div> - </div> - </div> - </footer> - ) -} - -export default Footer diff --git a/{{cookiecutter.project_slug}}/frontend/components/Layout.tsx b/{{cookiecutter.project_slug}}/frontend/components/Layout.tsx deleted file mode 100644 index 8cc6b346..00000000 --- a/{{cookiecutter.project_slug}}/frontend/components/Layout.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { Inter } from 'next/font/google' -import { ReactNode } from 'react' - -import Footer from './Footer' -import NavBar from './NavBar' - -const inter = Inter({ subsets: ['latin'] }) - -const Layout = ({ children }: { children: ReactNode }) => { - return ( - <div className={`${inter.className}`}> - <NavBar /> - <main className={`container mx-auto min-h-48 ${inter.className}`}>{children}</main> - <Footer /> - </div> - ) -} - -export default Layout diff --git a/{{cookiecutter.project_slug}}/frontend/components/NavBar.tsx b/{{cookiecutter.project_slug}}/frontend/components/NavBar.tsx deleted file mode 100644 index 7ef98a82..00000000 --- a/{{cookiecutter.project_slug}}/frontend/components/NavBar.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import Image from 'next/image' -import Link from 'next/link' - -const NavBar = () => { - return ( - <nav className='bg-gray-800 p-4'> - <div className='container mx-auto'> - <div className='flex items-center gap-4 text-lg font-bold text-white'> - <Image src='/scaf-logo.png' alt='Scaf Logo' width={60} height={75} /> - <Link href='/'>Home</Link> - <Link href='/about'>About</Link> - </div> - </div> - </nav> - ) -} - -export default NavBar diff --git a/{{cookiecutter.project_slug}}/frontend/lib/apolloClient.ts b/{{cookiecutter.project_slug}}/frontend/lib/apolloClient.ts deleted file mode 100644 index 68674946..00000000 --- a/{{cookiecutter.project_slug}}/frontend/lib/apolloClient.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { ApolloClient, HttpLink, InMemoryCache, NormalizedCacheObject, from } from '@apollo/client' -import { setContext } from '@apollo/client/link/context' -import { onError } from '@apollo/client/link/error' -import merge from 'deepmerge' -import isEqual from 'lodash/isEqual' -import type { AppProps } from 'next/app' -import { useRef } from 'react' - -export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__' - -let apolloClient: ApolloClient<NormalizedCacheObject> | undefined - -const errorLink = onError(({ graphQLErrors, networkError }) => { - if (graphQLErrors) - graphQLErrors.forEach(({ message, locations, path }) => - console.log(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`) - ) - if (networkError) console.log(`[Network error]: ${networkError}`) -}) - -const httpLink = new HttpLink({ - uri: - typeof window === 'undefined' - ? process.env.NEXT_GRAPHQL_ENDPOINT || 'http://backend:8000/graphql/' - : process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT || 'http://localhost:8000/graphql/', - credentials: 'include' -}) - -const authLink = setContext((_, { headers }) => { - const token = typeof window !== 'undefined' ? localStorage.getItem('token') : null - return { - headers: { - ...headers, - authorization: token ? `Bearer ${token}` : '' - } - } -}) - -function createApolloClient() { - return new ApolloClient({ - ssrMode: typeof window === 'undefined', - link: from([errorLink, authLink, httpLink]), - cache: new InMemoryCache() - }) -} - -export function initializeApollo(initialState: NormalizedCacheObject | null = null) { - const _apolloClient = apolloClient ?? createApolloClient() - // the initial state gets hydrated here - if (initialState) { - // Get existing cache, loaded during client side data fetching - const existingCache = _apolloClient.extract() - - // Merge the initialState from getStaticProps/getServerSideProps - // in the existing cache - const data = merge(existingCache, initialState, { - // combine arrays using object equality (like in sets) - arrayMerge: (destinationArray, sourceArray) => [ - ...sourceArray, - ...destinationArray.filter(d => sourceArray.every(s => !isEqual(d, s))) - ] - }) - // Restore the cache with the merged data - _apolloClient.cache.restore(data) - } - // For SSR always create a new Apollo Client - if (typeof window === 'undefined') return _apolloClient - // Create the Apollo Client once in the client - if (!apolloClient) apolloClient = _apolloClient - return _apolloClient -} - -export function addApolloState(client: typeof apolloClient, pageProps: AppProps['pageProps']) { - if (pageProps?.props) { - pageProps.props[APOLLO_STATE_PROP_NAME] = client?.cache.extract() - } - return pageProps -} - -export function useApollo(pageProps: AppProps['pageProps']) { - const state = pageProps[APOLLO_STATE_PROP_NAME] - const storeRef = useRef<ApolloClient<NormalizedCacheObject>>() - if (!storeRef.current) { - storeRef.current = initializeApollo(state) - } - return storeRef.current -} diff --git a/{{cookiecutter.project_slug}}/frontend/next.config.mjs b/{{cookiecutter.project_slug}}/frontend/next.config.mjs deleted file mode 100644 index 8368bdf6..00000000 --- a/{{cookiecutter.project_slug}}/frontend/next.config.mjs +++ /dev/null @@ -1,6 +0,0 @@ -/** @type {import('next').NextConfig} */ -const nextConfig = { - reactStrictMode: true -} - -export default nextConfig diff --git a/{{cookiecutter.project_slug}}/frontend/package-lock.json b/{{cookiecutter.project_slug}}/frontend/package-lock.json deleted file mode 100644 index 9d46e140..00000000 --- a/{{cookiecutter.project_slug}}/frontend/package-lock.json +++ /dev/null @@ -1,11853 +0,0 @@ -{ - "name": "{{ cookiecutter.project_name }}", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "{{ cookiecutter.project_name }}", - "version": "0.1.0", - "dependencies": { - "@apollo/client": "^3.10.8", - "@testing-library/jest-dom": "^6.5.0", - "@testing-library/user-event": "^14.5.2", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "clsx": "^2.1.1", - "deepmerge": "^4.3.1", - "eslint-plugin-unused-imports": "^3.2.0", - "lodash": "^4.17.21", - "next": "14.2.10", - "react": "^18", - "react-dom": "^18" - }, - "devDependencies": { - "@graphql-codegen/cli": "^5.0.2", - "@graphql-codegen/client-preset": "^4.3.2", - "@graphql-typed-document-node/core": "^3.2.0", - "@testing-library/react": "^16.0.0", - "@types/lodash": "^4.17.6", - "@types/node": "20.16.5", - "@types/react": "18.3.5", - "@types/react-dom": "^18", - "@vitejs/plugin-react": "^4.3.1", - "eslint": "^8.57.0", - "eslint-config-next": "14.2.4", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-react": "^7.35.2", - "eslint-plugin-react-hooks": "^4.6.2", - "graphql": "^16.9.0", - "husky": "^9.0.11", - "jsdom": "^24.1.0", - "postcss": "^8", - "prettier": "^3.3.2", - "prettier-plugin-tailwindcss": "^0.6.5", - "tailwindcss": "^3.4.1", - "typescript": "5.6.2", - "vitest": "^1.6.0" - } - }, - "node_modules/@adobe/css-tools": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", - "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==" - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@apollo/client": { - "version": "3.10.8", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.10.8.tgz", - "integrity": "sha512-UaaFEitRrPRWV836wY2L7bd3HRCfbMie1jlYMcmazFAK23MVhz/Uq7VG1nwbotPb5xzFsw5RF4Wnp2G3dWPM3g==", - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "@wry/caches": "^1.0.0", - "@wry/equality": "^0.5.6", - "@wry/trie": "^0.5.0", - "graphql-tag": "^2.12.6", - "hoist-non-react-statics": "^3.3.2", - "optimism": "^0.18.0", - "prop-types": "^15.7.2", - "rehackt": "^0.1.0", - "response-iterator": "^0.2.6", - "symbol-observable": "^4.0.0", - "ts-invariant": "^0.10.3", - "tslib": "^2.3.0", - "zen-observable-ts": "^1.2.5" - }, - "peerDependencies": { - "graphql": "^15.0.0 || ^16.0.0", - "graphql-ws": "^5.5.5", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "subscriptions-transport-ws": "^0.9.0 || ^0.11.0" - }, - "peerDependenciesMeta": { - "graphql-ws": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - }, - "subscriptions-transport-ws": { - "optional": true - } - } - }, - "node_modules/@ardatan/relay-compiler": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/@ardatan/relay-compiler/-/relay-compiler-12.0.0.tgz", - "integrity": "sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==", - "dev": true, - "dependencies": { - "@babel/core": "^7.14.0", - "@babel/generator": "^7.14.0", - "@babel/parser": "^7.14.0", - "@babel/runtime": "^7.0.0", - "@babel/traverse": "^7.14.0", - "@babel/types": "^7.0.0", - "babel-preset-fbjs": "^3.4.0", - "chalk": "^4.0.0", - "fb-watchman": "^2.0.0", - "fbjs": "^3.0.0", - "glob": "^7.1.1", - "immutable": "~3.7.6", - "invariant": "^2.2.4", - "nullthrows": "^1.1.1", - "relay-runtime": "12.0.0", - "signedsource": "^1.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "relay-compiler": "bin/relay-compiler" - }, - "peerDependencies": { - "graphql": "*" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/@ardatan/relay-compiler/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/@ardatan/relay-compiler/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@ardatan/sync-fetch": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@ardatan/sync-fetch/-/sync-fetch-0.0.1.tgz", - "integrity": "sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==", - "dev": true, - "dependencies": { - "node-fetch": "^2.6.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", - "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", - "dependencies": { - "@babel/highlight": "^7.24.7", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", - "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", - "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helpers": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", - "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz", - "integrity": "sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", - "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", - "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz", - "integrity": "sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", - "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", - "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", - "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", - "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", - "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-member-expression-to-functions": "^7.24.7", - "@babel/helper-optimise-call-expression": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", - "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", - "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", - "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", - "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", - "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", - "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", - "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", - "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.24.7", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", - "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", - "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", - "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", - "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", - "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", - "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", - "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz", - "integrity": "sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", - "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/template": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz", - "integrity": "sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz", - "integrity": "sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-flow": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", - "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", - "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", - "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", - "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", - "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-simple-access": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", - "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-replace-supers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", - "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", - "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", - "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", - "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.24.7", - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/plugin-syntax-jsx": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz", - "integrity": "sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz", - "integrity": "sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", - "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", - "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", - "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", - "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", - "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", - "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-environment-visitor": "^7.24.7", - "@babel/helper-function-name": "^7.24.7", - "@babel/helper-hoist-variables": "^7.24.7", - "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", - "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.24.7", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@graphql-codegen/add": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz", - "integrity": "sha512-SxXPmramkth8XtBlAHu4H4jYcYXM/o3p01+psU+0NADQowA8jtYkK6MW5rV6T+CxkEaNZItfSmZRPgIuypcqnA==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/cli": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-5.0.2.tgz", - "integrity": "sha512-MBIaFqDiLKuO4ojN6xxG9/xL9wmfD3ZjZ7RsPjwQnSHBCUXnEkdKvX+JVpx87Pq29Ycn8wTJUguXnTZ7Di0Mlw==", - "dev": true, - "dependencies": { - "@babel/generator": "^7.18.13", - "@babel/template": "^7.18.10", - "@babel/types": "^7.18.13", - "@graphql-codegen/client-preset": "^4.2.2", - "@graphql-codegen/core": "^4.0.2", - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-tools/apollo-engine-loader": "^8.0.0", - "@graphql-tools/code-file-loader": "^8.0.0", - "@graphql-tools/git-loader": "^8.0.0", - "@graphql-tools/github-loader": "^8.0.0", - "@graphql-tools/graphql-file-loader": "^8.0.0", - "@graphql-tools/json-file-loader": "^8.0.0", - "@graphql-tools/load": "^8.0.0", - "@graphql-tools/prisma-loader": "^8.0.0", - "@graphql-tools/url-loader": "^8.0.0", - "@graphql-tools/utils": "^10.0.0", - "@whatwg-node/fetch": "^0.8.0", - "chalk": "^4.1.0", - "cosmiconfig": "^8.1.3", - "debounce": "^1.2.0", - "detect-indent": "^6.0.0", - "graphql-config": "^5.0.2", - "inquirer": "^8.0.0", - "is-glob": "^4.0.1", - "jiti": "^1.17.1", - "json-to-pretty-yaml": "^1.2.2", - "listr2": "^4.0.5", - "log-symbols": "^4.0.0", - "micromatch": "^4.0.5", - "shell-quote": "^1.7.3", - "string-env-interpolation": "^1.0.1", - "ts-log": "^2.2.3", - "tslib": "^2.4.0", - "yaml": "^2.3.1", - "yargs": "^17.0.0" - }, - "bin": { - "gql-gen": "cjs/bin.js", - "graphql-code-generator": "cjs/bin.js", - "graphql-codegen": "cjs/bin.js", - "graphql-codegen-esm": "esm/bin.js" - }, - "peerDependencies": { - "@parcel/watcher": "^2.1.0", - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - }, - "peerDependenciesMeta": { - "@parcel/watcher": { - "optional": true - } - } - }, - "node_modules/@graphql-codegen/client-preset": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@graphql-codegen/client-preset/-/client-preset-4.3.2.tgz", - "integrity": "sha512-42jHyG6u2uFDIVNvzue8zR529aPT16EYIJQmvMk8XuYHo3PneQVlWmQ3j2fBy+RuWCBzpJKPKm7IGSKiw19nmg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7", - "@graphql-codegen/add": "^5.0.3", - "@graphql-codegen/gql-tag-operations": "4.0.9", - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-codegen/typed-document-node": "^5.0.9", - "@graphql-codegen/typescript": "^4.0.9", - "@graphql-codegen/typescript-operations": "^4.2.3", - "@graphql-codegen/visitor-plugin-common": "^5.3.1", - "@graphql-tools/documents": "^1.0.0", - "@graphql-tools/utils": "^10.0.0", - "@graphql-typed-document-node/core": "3.2.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/core": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-4.0.2.tgz", - "integrity": "sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-tools/schema": "^10.0.0", - "@graphql-tools/utils": "^10.0.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/gql-tag-operations": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.9.tgz", - "integrity": "sha512-lVgu1HClel896HqZAEjynatlU6eJrYOw+rh05DPgM150xvmb7Gz5TnRHA2vfwlDNIXDaToAIpz5RFfkjjnYM1Q==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-codegen/visitor-plugin-common": "5.3.1", - "@graphql-tools/utils": "^10.0.0", - "auto-bind": "~4.0.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/plugin-helpers": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.4.tgz", - "integrity": "sha512-MOIuHFNWUnFnqVmiXtrI+4UziMTYrcquljaI5f/T/Bc7oO7sXcfkAvgkNWEEi9xWreYwvuer3VHCuPI/lAFWbw==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.0.0", - "change-case-all": "1.0.15", - "common-tags": "1.8.2", - "import-from": "4.0.0", - "lodash": "~4.17.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/schema-ast": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-4.1.0.tgz", - "integrity": "sha512-kZVn0z+th9SvqxfKYgztA6PM7mhnSZaj4fiuBWvMTqA+QqQ9BBed6Pz41KuD/jr0gJtnlr2A4++/0VlpVbCTmQ==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.3", - "@graphql-tools/utils": "^10.0.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/typed-document-node": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typed-document-node/-/typed-document-node-5.0.9.tgz", - "integrity": "sha512-Wx6fyA4vpfIbfNTMiWUECGnjqzKkJdEbZHxVMIegiCBPzBYPAJV4mZZcildLAfm2FtZcgW4YKtFoTbnbXqPB3w==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-codegen/visitor-plugin-common": "5.3.1", - "auto-bind": "~4.0.0", - "change-case-all": "1.0.15", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/typescript": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-4.0.9.tgz", - "integrity": "sha512-0O35DMR4d/ctuHL1Zo6mRUUzp0BoszKfeWsa6sCm/g70+S98+hEfTwZNDkQHylLxapiyjssF9uw/F+sXqejqLw==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-codegen/schema-ast": "^4.0.2", - "@graphql-codegen/visitor-plugin-common": "5.3.1", - "auto-bind": "~4.0.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/typescript-operations": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-4.2.3.tgz", - "integrity": "sha512-6z7avSSOr03l5SyKbeDs7MzRyGwnQFSCqQm8Om5wIuoIgXVu2gXRmcJAY/I7SLdAy9xbF4Sho7XNqieFM2CAFQ==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-codegen/typescript": "^4.0.9", - "@graphql-codegen/visitor-plugin-common": "5.3.1", - "auto-bind": "~4.0.0", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/visitor-plugin-common": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.3.1.tgz", - "integrity": "sha512-MktoBdNZhSmugiDjmFl1z6rEUUaqyxtFJYWnDilE7onkPgyw//O0M+TuPBJPBWdyV6J2ond0Hdqtq+rkghgSIQ==", - "dev": true, - "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.4", - "@graphql-tools/optimize": "^2.0.0", - "@graphql-tools/relay-operation-optimizer": "^7.0.0", - "@graphql-tools/utils": "^10.0.0", - "auto-bind": "~4.0.0", - "change-case-all": "1.0.15", - "dependency-graph": "^0.11.0", - "graphql-tag": "^2.11.0", - "parse-filepath": "^1.0.2", - "tslib": "~2.6.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-tools/apollo-engine-loader": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-8.0.1.tgz", - "integrity": "sha512-NaPeVjtrfbPXcl+MLQCJLWtqe2/E4bbAqcauEOQ+3sizw1Fc2CNmhHRF8a6W4D0ekvTRRXAMptXYgA2uConbrA==", - "dev": true, - "dependencies": { - "@ardatan/sync-fetch": "^0.0.1", - "@graphql-tools/utils": "^10.0.13", - "@whatwg-node/fetch": "^0.9.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/apollo-engine-loader/node_modules/@whatwg-node/events": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", - "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", - "dev": true, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/apollo-engine-loader/node_modules/@whatwg-node/fetch": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", - "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", - "dev": true, - "dependencies": { - "@whatwg-node/node-fetch": "^0.5.7", - "urlpattern-polyfill": "^10.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/apollo-engine-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", - "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", - "dev": true, - "dependencies": { - "@kamilkisiela/fast-url-parser": "^1.1.4", - "@whatwg-node/events": "^0.1.0", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/apollo-engine-loader/node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true - }, - "node_modules/@graphql-tools/batch-execute": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-9.0.4.tgz", - "integrity": "sha512-kkebDLXgDrep5Y0gK1RN3DMUlLqNhg60OAz0lTCqrYeja6DshxLtLkj+zV4mVbBA4mQOEoBmw6g1LZs3dA84/w==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.0.13", - "dataloader": "^2.2.2", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/code-file-loader": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-8.1.2.tgz", - "integrity": "sha512-GrLzwl1QV2PT4X4TEEfuTmZYzIZHLqoTGBjczdUzSqgCCcqwWzLB3qrJxFQfI8e5s1qZ1bhpsO9NoMn7tvpmyA==", - "dev": true, - "dependencies": { - "@graphql-tools/graphql-tag-pluck": "8.3.1", - "@graphql-tools/utils": "^10.0.13", - "globby": "^11.0.3", - "tslib": "^2.4.0", - "unixify": "^1.0.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/delegate": { - "version": "10.0.13", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-10.0.13.tgz", - "integrity": "sha512-9l7cwrHQFbvR6zhZOKYABa3ffqgyV51gNglammupXhptE3Z94p6A6hP0hLw7GHErkm6MiQINl3VBVpFJDlrZuQ==", - "dev": true, - "dependencies": { - "@graphql-tools/batch-execute": "^9.0.4", - "@graphql-tools/executor": "^1.2.8", - "@graphql-tools/schema": "^10.0.4", - "@graphql-tools/utils": "^10.2.3", - "dataloader": "^2.2.2", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/documents": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/documents/-/documents-1.0.1.tgz", - "integrity": "sha512-aweoMH15wNJ8g7b2r4C4WRuJxZ0ca8HtNO54rkye/3duxTkW4fGBEutCx03jCIr5+a1l+4vFJNP859QnAVBVCA==", - "dev": true, - "dependencies": { - "lodash.sortby": "^4.7.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/executor": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.2.8.tgz", - "integrity": "sha512-0qZs/iuRiYRir7bBkA7oN+21wwmSMPQuFK8WcAcxUYJZRhvnlrJ8Nid++PN4OCzTgHPV70GNFyXOajseVCCffA==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.2.3", - "@graphql-typed-document-node/core": "3.2.0", - "@repeaterjs/repeater": "^3.0.4", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/executor-graphql-ws": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-1.2.0.tgz", - "integrity": "sha512-tSYC1QdrabWexLrYV0UI3uRGbde9WCY/bRhq6Jc+VXMZcfq6ea6pP5NEAVTfwbhUQ4xZvJABVVbKXtKb9uTg1w==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.3.0", - "@types/ws": "^8.0.0", - "graphql-ws": "^5.14.0", - "isomorphic-ws": "^5.0.0", - "tslib": "^2.4.0", - "ws": "^8.17.1" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/executor-http": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-1.1.2.tgz", - "integrity": "sha512-Yssoh2+GBcoPcL6Jf9X+G+cp8RhiKz6m5R/BLLN0mdg6t02TYANYZV76dMBRPX93xaoIpjl94JkttC6O6ejwWg==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.3.1", - "@repeaterjs/repeater": "^3.0.4", - "@whatwg-node/fetch": "^0.9.0", - "extract-files": "^11.0.0", - "meros": "^1.2.1", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/executor-http/node_modules/@whatwg-node/events": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", - "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", - "dev": true, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/executor-http/node_modules/@whatwg-node/fetch": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", - "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", - "dev": true, - "dependencies": { - "@whatwg-node/node-fetch": "^0.5.7", - "urlpattern-polyfill": "^10.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/executor-http/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", - "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", - "dev": true, - "dependencies": { - "@kamilkisiela/fast-url-parser": "^1.1.4", - "@whatwg-node/events": "^0.1.0", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/executor-http/node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true - }, - "node_modules/@graphql-tools/executor-legacy-ws": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-1.1.0.tgz", - "integrity": "sha512-k+6ZyiaAd8SmwuzbEOfA/LVkuI1nqidhoMw+CJ7c41QGOjSMzc0VS0UZbJyeitI0n7a+uP/Meln1wjzJ2ReDtQ==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.3.0", - "@types/ws": "^8.0.0", - "isomorphic-ws": "^5.0.0", - "tslib": "^2.4.0", - "ws": "^8.17.1" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/git-loader": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-8.0.6.tgz", - "integrity": "sha512-FQFO4H5wHAmHVyuUQrjvPE8re3qJXt50TWHuzrK3dEaief7JosmlnkLMDMbMBwtwITz9u1Wpl6doPhT2GwKtlw==", - "dev": true, - "dependencies": { - "@graphql-tools/graphql-tag-pluck": "8.3.1", - "@graphql-tools/utils": "^10.0.13", - "is-glob": "4.0.3", - "micromatch": "^4.0.4", - "tslib": "^2.4.0", - "unixify": "^1.0.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/github-loader": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-8.0.1.tgz", - "integrity": "sha512-W4dFLQJ5GtKGltvh/u1apWRFKBQOsDzFxO9cJkOYZj1VzHCpRF43uLST4VbCfWve+AwBqOuKr7YgkHoxpRMkcg==", - "dev": true, - "dependencies": { - "@ardatan/sync-fetch": "^0.0.1", - "@graphql-tools/executor-http": "^1.0.9", - "@graphql-tools/graphql-tag-pluck": "^8.0.0", - "@graphql-tools/utils": "^10.0.13", - "@whatwg-node/fetch": "^0.9.0", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/github-loader/node_modules/@whatwg-node/events": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", - "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", - "dev": true, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/github-loader/node_modules/@whatwg-node/fetch": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", - "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", - "dev": true, - "dependencies": { - "@whatwg-node/node-fetch": "^0.5.7", - "urlpattern-polyfill": "^10.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/github-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", - "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", - "dev": true, - "dependencies": { - "@kamilkisiela/fast-url-parser": "^1.1.4", - "@whatwg-node/events": "^0.1.0", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/github-loader/node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true - }, - "node_modules/@graphql-tools/graphql-file-loader": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-8.0.1.tgz", - "integrity": "sha512-7gswMqWBabTSmqbaNyWSmRRpStWlcCkBc73E6NZNlh4YNuiyKOwbvSkOUYFOqFMfEL+cFsXgAvr87Vz4XrYSbA==", - "dev": true, - "dependencies": { - "@graphql-tools/import": "7.0.1", - "@graphql-tools/utils": "^10.0.13", - "globby": "^11.0.3", - "tslib": "^2.4.0", - "unixify": "^1.0.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/graphql-tag-pluck": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.3.1.tgz", - "integrity": "sha512-ujits9tMqtWQQq4FI4+qnVPpJvSEn7ogKtyN/gfNT+ErIn6z1e4gyVGQpTK5sgAUXq1lW4gU/5fkFFC5/sL2rQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.22.9", - "@babel/parser": "^7.16.8", - "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/traverse": "^7.16.8", - "@babel/types": "^7.16.8", - "@graphql-tools/utils": "^10.0.13", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/import": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-7.0.1.tgz", - "integrity": "sha512-935uAjAS8UAeXThqHfYVr4HEAp6nHJ2sximZKO1RzUTq5WoALMAhhGARl0+ecm6X+cqNUwIChJbjtaa6P/ML0w==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.0.13", - "resolve-from": "5.0.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/import/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@graphql-tools/json-file-loader": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-8.0.1.tgz", - "integrity": "sha512-lAy2VqxDAHjVyqeJonCP6TUemrpYdDuKt25a10X6zY2Yn3iFYGnuIDQ64cv3ytyGY6KPyPB+Kp+ZfOkNDG3FQA==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.0.13", - "globby": "^11.0.3", - "tslib": "^2.4.0", - "unixify": "^1.0.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/load": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-8.0.2.tgz", - "integrity": "sha512-S+E/cmyVmJ3CuCNfDuNF2EyovTwdWfQScXv/2gmvJOti2rGD8jTt9GYVzXaxhblLivQR9sBUCNZu/w7j7aXUCA==", - "dev": true, - "dependencies": { - "@graphql-tools/schema": "^10.0.3", - "@graphql-tools/utils": "^10.0.13", - "p-limit": "3.1.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/merge": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.4.tgz", - "integrity": "sha512-MivbDLUQ+4Q8G/Hp/9V72hbn810IJDEZQ57F01sHnlrrijyadibfVhaQfW/pNH+9T/l8ySZpaR/DpL5i+ruZ+g==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.0.13", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/optimize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/optimize/-/optimize-2.0.0.tgz", - "integrity": "sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/prisma-loader": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-8.0.4.tgz", - "integrity": "sha512-hqKPlw8bOu/GRqtYr0+dINAI13HinTVYBDqhwGAPIFmLr5s+qKskzgCiwbsckdrb5LWVFmVZc+UXn80OGiyBzg==", - "dev": true, - "dependencies": { - "@graphql-tools/url-loader": "^8.0.2", - "@graphql-tools/utils": "^10.0.13", - "@types/js-yaml": "^4.0.0", - "@whatwg-node/fetch": "^0.9.0", - "chalk": "^4.1.0", - "debug": "^4.3.1", - "dotenv": "^16.0.0", - "graphql-request": "^6.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "jose": "^5.0.0", - "js-yaml": "^4.0.0", - "lodash": "^4.17.20", - "scuid": "^1.1.0", - "tslib": "^2.4.0", - "yaml-ast-parser": "^0.0.43" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/@whatwg-node/events": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", - "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", - "dev": true, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/@whatwg-node/fetch": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", - "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", - "dev": true, - "dependencies": { - "@whatwg-node/node-fetch": "^0.5.7", - "urlpattern-polyfill": "^10.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", - "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", - "dev": true, - "dependencies": { - "@kamilkisiela/fast-url-parser": "^1.1.4", - "@whatwg-node/events": "^0.1.0", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true - }, - "node_modules/@graphql-tools/relay-operation-optimizer": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.0.1.tgz", - "integrity": "sha512-y0ZrQ/iyqWZlsS/xrJfSir3TbVYJTYmMOu4TaSz6F4FRDTQ3ie43BlKkhf04rC28pnUOS4BO9pDcAo1D30l5+A==", - "dev": true, - "dependencies": { - "@ardatan/relay-compiler": "12.0.0", - "@graphql-tools/utils": "^10.0.13", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/schema": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.4.tgz", - "integrity": "sha512-HuIwqbKxPaJujox25Ra4qwz0uQzlpsaBOzO6CVfzB/MemZdd+Gib8AIvfhQArK0YIN40aDran/yi+E5Xf0mQww==", - "dev": true, - "dependencies": { - "@graphql-tools/merge": "^9.0.3", - "@graphql-tools/utils": "^10.2.1", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/url-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-8.0.2.tgz", - "integrity": "sha512-1dKp2K8UuFn7DFo1qX5c1cyazQv2h2ICwA9esHblEqCYrgf69Nk8N7SODmsfWg94OEaI74IqMoM12t7eIGwFzQ==", - "dev": true, - "dependencies": { - "@ardatan/sync-fetch": "^0.0.1", - "@graphql-tools/delegate": "^10.0.4", - "@graphql-tools/executor-graphql-ws": "^1.1.2", - "@graphql-tools/executor-http": "^1.0.9", - "@graphql-tools/executor-legacy-ws": "^1.0.6", - "@graphql-tools/utils": "^10.0.13", - "@graphql-tools/wrap": "^10.0.2", - "@types/ws": "^8.0.0", - "@whatwg-node/fetch": "^0.9.0", - "isomorphic-ws": "^5.0.0", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.11", - "ws": "^8.12.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/url-loader/node_modules/@whatwg-node/events": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", - "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", - "dev": true, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/url-loader/node_modules/@whatwg-node/fetch": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", - "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", - "dev": true, - "dependencies": { - "@whatwg-node/node-fetch": "^0.5.7", - "urlpattern-polyfill": "^10.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/url-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.5.11", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", - "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", - "dev": true, - "dependencies": { - "@kamilkisiela/fast-url-parser": "^1.1.4", - "@whatwg-node/events": "^0.1.0", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@graphql-tools/url-loader/node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true - }, - "node_modules/@graphql-tools/utils": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.3.1.tgz", - "integrity": "sha512-Yhk1F0MNk4/ctgl3d0DKq++ZPovvZuh1ixWuUEVAxrFloYOAVwJ+rvGI1lsopArdJly8QXClT9lkvOxQszMw/w==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "cross-inspect": "1.0.0", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/wrap": { - "version": "10.0.5", - "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-10.0.5.tgz", - "integrity": "sha512-Cbr5aYjr3HkwdPvetZp1cpDWTGdD1Owgsb3z/ClzhmrboiK86EnQDxDvOJiQkDCPWE9lNBwj8Y4HfxroY0D9DQ==", - "dev": true, - "dependencies": { - "@graphql-tools/delegate": "^10.0.4", - "@graphql-tools/schema": "^10.0.3", - "@graphql-tools/utils": "^10.1.1", - "tslib": "^2.4.0", - "value-or-promise": "^1.0.12" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-typed-document-node/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", - "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@kamilkisiela/fast-url-parser": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@kamilkisiela/fast-url-parser/-/fast-url-parser-1.1.4.tgz", - "integrity": "sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==", - "dev": true - }, - "node_modules/@next/env": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.10.tgz", - "integrity": "sha512-dZIu93Bf5LUtluBXIv4woQw2cZVZ2DJTjax5/5DOs3lzEOeKLy7GxRSr4caK9/SCPdaW6bCgpye6+n4Dh9oJPw==" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.4.tgz", - "integrity": "sha512-svSFxW9f3xDaZA3idQmlFw7SusOuWTpDTAeBlO3AEPDltrraV+lqs7mAc6A27YdnpQVVIA3sODqUAAHdWhVWsA==", - "dev": true, - "dependencies": { - "glob": "10.3.10" - } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.10.tgz", - "integrity": "sha512-V3z10NV+cvMAfxQUMhKgfQnPbjw+Ew3cnr64b0lr8MDiBJs3eLnM6RpGC46nhfMZsiXgQngCJKWGTC/yDcgrDQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.10.tgz", - "integrity": "sha512-Y0TC+FXbFUQ2MQgimJ/7Ina2mXIKhE7F+GUe1SgnzRmwFY3hX2z8nyVCxE82I2RicspdkZnSWMn4oTjIKz4uzA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.10.tgz", - "integrity": "sha512-ZfQ7yOy5zyskSj9rFpa0Yd7gkrBnJTkYVSya95hX3zeBG9E55Z6OTNPn1j2BTFWvOVVj65C3T+qsjOyVI9DQpA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.10.tgz", - "integrity": "sha512-n2i5o3y2jpBfXFRxDREr342BGIQCJbdAUi/K4q6Env3aSx8erM9VuKXHw5KNROK9ejFSPf0LhoSkU/ZiNdacpQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.10.tgz", - "integrity": "sha512-GXvajAWh2woTT0GKEDlkVhFNxhJS/XdDmrVHrPOA83pLzlGPQnixqxD8u3bBB9oATBKB//5e4vpACnx5Vaxdqg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.10.tgz", - "integrity": "sha512-opFFN5B0SnO+HTz4Wq4HaylXGFV+iHrVxd3YvREUX9K+xfc4ePbRrxqOuPOFjtSuiVouwe6uLeDtabjEIbkmDA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.10.tgz", - "integrity": "sha512-9NUzZuR8WiXTvv+EiU/MXdcQ1XUvFixbLIMNQiVHuzs7ZIFrJDLJDaOF1KaqttoTujpcxljM/RNAOmw1GhPPQQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.10.tgz", - "integrity": "sha512-fr3aEbSd1GeW3YUMBkWAu4hcdjZ6g4NBl1uku4gAn661tcxd1bHs1THWYzdsbTRLcCKLjrDZlNp6j2HTfrw+Bg==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.10.tgz", - "integrity": "sha512-UjeVoRGKNL2zfbcQ6fscmgjBAS/inHBh63mjIlfPg/NG8Yn2ztqylXt5qilYb6hoHIwaU2ogHknHWWmahJjgZQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@peculiar/asn1-schema": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz", - "integrity": "sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==", - "dev": true, - "dependencies": { - "asn1js": "^3.0.5", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2" - } - }, - "node_modules/@peculiar/json-schema": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", - "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", - "dev": true, - "dependencies": { - "tslib": "^2.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@peculiar/webcrypto": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz", - "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", - "dev": true, - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2", - "webcrypto-core": "^1.8.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@repeaterjs/repeater": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz", - "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==", - "dev": true - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", - "integrity": "sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==", - "dev": true - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, - "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", - "dependencies": { - "@swc/counter": "^0.1.3", - "tslib": "^2.4.0" - } - }, - "node_modules/@testing-library/dom": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.3.0.tgz", - "integrity": "sha512-pT/TYB2+IyMYkkB6lqpkzD7VFbsR0JBJtflK3cS68sCNWxmOhWwRm1XvVHlseNEorsNcxkYsb4sRDV3aNIpttg==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "peer": true, - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz", - "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==", - "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "lodash": "^4.17.21", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==" - }, - "node_modules/@testing-library/react": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.0.tgz", - "integrity": "sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@testing-library/dom": "^10.0.0", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@testing-library/user-event": { - "version": "14.5.2", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", - "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", - "peer": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/lodash": { - "version": "4.17.6", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.6.tgz", - "integrity": "sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA==", - "dev": true - }, - "node_modules/@types/node": { - "version": "20.16.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz", - "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==", - "dev": true, - "dependencies": { - "undici-types": "~6.19.2" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.12", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "devOptional": true - }, - "node_modules/@types/react": { - "version": "18.3.5", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.5.tgz", - "integrity": "sha512-WeqMfGJLGuLCqHGYRGHxnKrXcTitc6L/nBUWfWPcTarG3t9PsquqUMuVeXZeca+mglY4Vo5GZjCi0A3Or2lnxA==", - "devOptional": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/ws": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", - "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz", - "integrity": "sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw==", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/type-utils": "7.14.1", - "@typescript-eslint/utils": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", - "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.14.1.tgz", - "integrity": "sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA==", - "peer": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", - "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", - "peer": true, - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", - "peer": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", - "peer": true, - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", - "peer": true, - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "peer": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz", - "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.2.0", - "@typescript-eslint/visitor-keys": "7.2.0" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz", - "integrity": "sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ==", - "dependencies": { - "@typescript-eslint/typescript-estree": "7.14.1", - "@typescript-eslint/utils": "7.14.1", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz", - "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==", - "dev": true, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz", - "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.2.0", - "@typescript-eslint/visitor-keys": "7.2.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.14.1.tgz", - "integrity": "sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.14.1", - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/typescript-estree": "7.14.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz", - "integrity": "sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA==", - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.14.1.tgz", - "integrity": "sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg==", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz", - "integrity": "sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA==", - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "@typescript-eslint/visitor-keys": "7.14.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz", - "integrity": "sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA==", - "dependencies": { - "@typescript-eslint/types": "7.14.1", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz", - "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.2.0", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz", - "integrity": "sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.24.5", - "@babel/plugin-transform-react-jsx-self": "^7.24.5", - "@babel/plugin-transform-react-jsx-source": "^7.24.1", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0" - } - }, - "node_modules/@vitest/expect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", - "integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==", - "dev": true, - "dependencies": { - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz", - "integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==", - "dev": true, - "dependencies": { - "@vitest/utils": "1.6.0", - "p-limit": "^5.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner/node_modules/p-limit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", - "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vitest/runner/node_modules/yocto-queue": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", - "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vitest/snapshot": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz", - "integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==", - "dev": true, - "dependencies": { - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vitest/snapshot/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@vitest/snapshot/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@vitest/spy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz", - "integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==", - "dev": true, - "dependencies": { - "tinyspy": "^2.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz", - "integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==", - "dev": true, - "dependencies": { - "diff-sequences": "^29.6.3", - "estree-walker": "^3.0.3", - "loupe": "^2.3.7", - "pretty-format": "^29.7.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@vitest/utils/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@vitest/utils/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true - }, - "node_modules/@whatwg-node/events": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.0.3.tgz", - "integrity": "sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==", - "dev": true - }, - "node_modules/@whatwg-node/fetch": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.8.8.tgz", - "integrity": "sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==", - "dev": true, - "dependencies": { - "@peculiar/webcrypto": "^1.4.0", - "@whatwg-node/node-fetch": "^0.3.6", - "busboy": "^1.6.0", - "urlpattern-polyfill": "^8.0.0", - "web-streams-polyfill": "^3.2.1" - } - }, - "node_modules/@whatwg-node/node-fetch": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz", - "integrity": "sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==", - "dev": true, - "dependencies": { - "@whatwg-node/events": "^0.0.3", - "busboy": "^1.6.0", - "fast-querystring": "^1.1.1", - "fast-url-parser": "^1.1.3", - "tslib": "^2.3.1" - } - }, - "node_modules/@wry/caches": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz", - "integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@wry/context": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz", - "integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@wry/equality": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz", - "integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@wry/trie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz", - "integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", - "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", - "dev": true, - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/asn1js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", - "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", - "dev": true, - "dependencies": { - "pvtsutils": "^1.3.2", - "pvutils": "^1.1.3", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", - "dev": true - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/auto-bind": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", - "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.9.1.tgz", - "integrity": "sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", - "dev": true, - "dependencies": { - "deep-equal": "^2.0.5" - } - }, - "node_modules/babel-plugin-syntax-trailing-function-commas": { - "version": "7.0.0-beta.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", - "integrity": "sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==", - "dev": true - }, - "node_modules/babel-preset-fbjs": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz", - "integrity": "sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==", - "dev": true, - "dependencies": { - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-class-properties": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.0.0", - "@babel/plugin-syntax-jsx": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-member-expression-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-property-literals": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "babel-plugin-syntax-trailing-function-commas": "^7.0.0-beta.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001639", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001639.tgz", - "integrity": "sha512-eFHflNTBIlFwP2AIKaYuBQN/apnUoKNhBdza8ZnW/h2di4LCZ4xFqYlxUxo+LQ76KFI1PGcC1QDxMbxTZpSCAg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "node_modules/chai": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", - "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.0.8" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "dev": true, - "dependencies": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/change-case-all": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.15.tgz", - "integrity": "sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==", - "dev": true, - "dependencies": { - "change-case": "^4.1.2", - "is-lower-case": "^2.0.2", - "is-upper-case": "^2.0.2", - "lower-case": "^2.0.2", - "lower-case-first": "^2.0.2", - "sponge-case": "^1.0.1", - "swap-case": "^2.0.2", - "title-case": "^3.0.3", - "upper-case": "^2.0.2", - "upper-case-first": "^2.0.2" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/confbox": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.7.tgz", - "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", - "dev": true - }, - "node_modules/constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cross-fetch": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", - "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", - "dev": true, - "dependencies": { - "node-fetch": "^2.6.12" - } - }, - "node_modules/cross-inspect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.0.tgz", - "integrity": "sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==", - "dev": true, - "dependencies": { - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssstyle": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.0.1.tgz", - "integrity": "sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==", - "dev": true, - "dependencies": { - "rrweb-cssom": "^0.6.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cssstyle/node_modules/rrweb-cssom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz", - "integrity": "sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==", - "dev": true - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "devOptional": true - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", - "dev": true - }, - "node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/dataloader": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", - "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==", - "dev": true - }, - "node_modules/debounce": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", - "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decimal.js": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", - "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", - "dev": true - }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/deep-equal": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", - "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.5", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.2", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true - }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", - "peer": true - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dset": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", - "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/electron-to-chromium": { - "version": "1.4.816", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz", - "integrity": "sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/enhanced-resolve": { - "version": "5.17.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz", - "integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.0.19", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz", - "integrity": "sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-next": { - "version": "14.2.4", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.4.tgz", - "integrity": "sha512-Qr0wMgG9m6m4uYy2jrYJmyuNlYZzPRQq5Kvb9IDlYwn+7yq6W6sfMNFgb+9guM1KYwuIo6TIaiFhZJ6SnQ/Efw==", - "dev": true, - "dependencies": { - "@next/eslint-plugin-next": "14.2.4", - "@rushstack/eslint-patch": "^1.3.3", - "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsx-a11y": "^6.7.1", - "eslint-plugin-react": "^7.33.2", - "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-config-next/node_modules/@typescript-eslint/parser": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", - "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.2.0", - "@typescript-eslint/types": "7.2.0", - "@typescript-eslint/typescript-estree": "7.2.0", - "@typescript-eslint/visitor-keys": "7.2.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-config-next/node_modules/eslint-import-resolver-typescript": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", - "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", - "dev": true, - "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "fast-glob": "^3.3.1", - "get-tsconfig": "^4.5.0", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", - "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.7", - "array.prototype.findlastindex": "^1.2.3", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.8.0", - "hasown": "^2.0.0", - "is-core-module": "^2.13.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.7", - "object.groupby": "^1.0.1", - "object.values": "^1.1.7", - "semver": "^6.3.1", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz", - "integrity": "sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g==", - "dev": true, - "dependencies": { - "aria-query": "~5.1.3", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.9.1", - "axobject-query": "~3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "es-iterator-helpers": "^1.0.19", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.0" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.35.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.35.2.tgz", - "integrity": "sha512-Rbj2R9zwP2GYNcIak4xoAMV57hrBh3hTaR0k7hVjwCQgryE/pw5px4b13EYjduOI0hfXyZhwBxaGpOTbWSGzKQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.2", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.0.19", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.0", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.11", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-unused-imports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz", - "integrity": "sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ==", - "dependencies": { - "eslint-rule-composer": "^0.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "6 - 7", - "eslint": "8" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - } - } - }, - "node_modules/eslint-rule-composer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/external-editor/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extract-files": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz", - "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==", - "dev": true, - "engines": { - "node": "^12.20 || >= 14.13" - }, - "funding": { - "url": "https://github.com/sponsors/jaydenseric" - } - }, - "node_modules/fast-decode-uri-component": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", - "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "node_modules/fast-querystring": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", - "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", - "dev": true, - "dependencies": { - "fast-decode-uri-component": "^1.0.1" - } - }, - "node_modules/fast-url-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", - "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", - "dev": true, - "dependencies": { - "punycode": "^1.3.2" - } - }, - "node_modules/fast-url-parser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fbjs": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", - "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", - "dev": true, - "dependencies": { - "cross-fetch": "^3.1.5", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^1.0.35" - } - }, - "node_modules/fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", - "dev": true - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", - "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.7.5", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz", - "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==", - "dev": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" - }, - "node_modules/graphql": { - "version": "16.9.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", - "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", - "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" - } - }, - "node_modules/graphql-config": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-5.0.3.tgz", - "integrity": "sha512-BNGZaoxIBkv9yy6Y7omvsaBUHOzfFcII3UN++tpH8MGOKFPFkCPZuwx09ggANMt8FgyWP1Od8SWPmrUEZca4NQ==", - "dev": true, - "dependencies": { - "@graphql-tools/graphql-file-loader": "^8.0.0", - "@graphql-tools/json-file-loader": "^8.0.0", - "@graphql-tools/load": "^8.0.0", - "@graphql-tools/merge": "^9.0.0", - "@graphql-tools/url-loader": "^8.0.0", - "@graphql-tools/utils": "^10.0.0", - "cosmiconfig": "^8.1.0", - "jiti": "^1.18.2", - "minimatch": "^4.2.3", - "string-env-interpolation": "^1.0.1", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">= 16.0.0" - }, - "peerDependencies": { - "cosmiconfig-toml-loader": "^1.0.0", - "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - }, - "peerDependenciesMeta": { - "cosmiconfig-toml-loader": { - "optional": true - } - } - }, - "node_modules/graphql-config/node_modules/minimatch": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.3.tgz", - "integrity": "sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/graphql-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", - "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.2.0", - "cross-fetch": "^3.1.5" - }, - "peerDependencies": { - "graphql": "14 - 16" - } - }, - "node_modules/graphql-tag": { - "version": "2.12.6", - "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", - "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/graphql-ws": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.0.tgz", - "integrity": "sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A==", - "devOptional": true, - "workspaces": [ - "website" - ], - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "graphql": ">=0.11 <=16" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, - "dependencies": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", - "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", - "dev": true, - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/husky": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", - "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", - "dev": true, - "bin": { - "husky": "bin.mjs" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", - "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", - "dev": true, - "engines": { - "node": ">=12.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/inquirer": { - "version": "8.2.6", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", - "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^6.0.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/inquirer/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/inquirer/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "dependencies": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "dependencies": { - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", - "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz", - "integrity": "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "dependencies": { - "is-unc-path": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "dependencies": { - "which-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "dependencies": { - "unc-path-regex": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz", - "integrity": "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", - "dev": true, - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", - "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", - "dev": true, - "dependencies": { - "define-properties": "^1.2.1", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "reflect.getprototypeof": "^1.0.4", - "set-function-name": "^2.0.1" - } - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dev": true, - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jiti": { - "version": "1.21.6", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", - "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", - "dev": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/jose": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-5.6.3.tgz", - "integrity": "sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/panva" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "24.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.0.tgz", - "integrity": "sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==", - "dev": true, - "dependencies": { - "cssstyle": "^4.0.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.4.3", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.4", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.10", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.4", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0", - "ws": "^8.17.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "canvas": "^2.11.2" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json-to-pretty-yaml": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", - "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", - "dev": true, - "dependencies": { - "remedial": "^1.0.7", - "remove-trailing-spaces": "^1.0.6" - }, - "engines": { - "node": ">= 0.2.0" - } - }, - "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", - "dev": true - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dev": true, - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/listr2": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", - "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.5", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/listr2/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/local-pkg": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", - "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==", - "dev": true, - "dependencies": { - "mlly": "^1.4.2", - "pkg-types": "^1.0.3" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lower-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz", - "integrity": "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz", - "integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==", - "dev": true, - "engines": { - "node": "14 || >=16.14" - } - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "peer": true, - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/magic-string": { - "version": "0.30.10", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", - "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/meros": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz", - "integrity": "sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==", - "dev": true, - "engines": { - "node": ">=13" - }, - "peerDependencies": { - "@types/node": ">=13" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mlly": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.1.tgz", - "integrity": "sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==", - "dev": true, - "dependencies": { - "acorn": "^8.11.3", - "pathe": "^1.1.2", - "pkg-types": "^1.1.1", - "ufo": "^1.5.3" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/next": { - "version": "14.2.10", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.10.tgz", - "integrity": "sha512-sDDExXnh33cY3RkS9JuFEKaS4HmlWmDKP1VJioucCG6z5KuA008DPsDZOzi8UfqEk3Ii+2NCQSJrfbEWtZZfww==", - "dependencies": { - "@next/env": "14.2.10", - "@swc/helpers": "0.5.5", - "busboy": "1.6.0", - "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", - "postcss": "8.4.31", - "styled-jsx": "5.1.1" - }, - "bin": { - "next": "dist/bin/next" - }, - "engines": { - "node": ">=18.17.0" - }, - "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.10", - "@next/swc-darwin-x64": "14.2.10", - "@next/swc-linux-arm64-gnu": "14.2.10", - "@next/swc-linux-arm64-musl": "14.2.10", - "@next/swc-linux-x64-gnu": "14.2.10", - "@next/swc-linux-x64-musl": "14.2.10", - "@next/swc-win32-arm64-msvc": "14.2.10", - "@next/swc-win32-ia32-msvc": "14.2.10", - "@next/swc-win32-x64-msvc": "14.2.10" - }, - "peerDependencies": { - "@opentelemetry/api": "^1.1.0", - "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sass": "^1.3.0" - }, - "peerDependenciesMeta": { - "@opentelemetry/api": { - "optional": true - }, - "@playwright/test": { - "optional": true - }, - "sass": { - "optional": true - } - } - }, - "node_modules/next/node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true - }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nullthrows": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", - "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", - "dev": true - }, - "node_modules/nwsapi": { - "version": "2.2.10", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz", - "integrity": "sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dependencies": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optimism": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.0.tgz", - "integrity": "sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==", - "dependencies": { - "@wry/caches": "^1.0.0", - "@wry/context": "^0.7.0", - "@wry/trie": "^0.4.3", - "tslib": "^2.3.0" - } - }, - "node_modules/optimism/node_modules/@wry/trie": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.4.3.tgz", - "integrity": "sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==", - "dependencies": { - "tslib": "^2.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", - "dev": true, - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", - "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", - "dev": true, - "dependencies": { - "entities": "^4.4.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", - "dev": true, - "dependencies": { - "path-root-regex": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-types": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.1.3.tgz", - "integrity": "sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==", - "dev": true, - "dependencies": { - "confbox": "^0.1.7", - "mlly": "^1.7.1", - "pathe": "^1.1.2" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.11" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz", - "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", - "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettier-plugin-tailwindcss": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.5.tgz", - "integrity": "sha512-axfeOArc/RiGHjOIy9HytehlC0ZLeMaqY09mm8YCkMzznKiDkwFzOpBvtuhuv3xG5qB73+Mj7OCe2j/L1ryfuQ==", - "dev": true, - "engines": { - "node": ">=14.21.3" - }, - "peerDependencies": { - "@ianvs/prettier-plugin-sort-imports": "*", - "@prettier/plugin-pug": "*", - "@shopify/prettier-plugin-liquid": "*", - "@trivago/prettier-plugin-sort-imports": "*", - "@zackad/prettier-plugin-twig-melody": "*", - "prettier": "^3.0", - "prettier-plugin-astro": "*", - "prettier-plugin-css-order": "*", - "prettier-plugin-import-sort": "*", - "prettier-plugin-jsdoc": "*", - "prettier-plugin-marko": "*", - "prettier-plugin-organize-attributes": "*", - "prettier-plugin-organize-imports": "*", - "prettier-plugin-sort-imports": "*", - "prettier-plugin-style-order": "*", - "prettier-plugin-svelte": "*" - }, - "peerDependenciesMeta": { - "@ianvs/prettier-plugin-sort-imports": { - "optional": true - }, - "@prettier/plugin-pug": { - "optional": true - }, - "@shopify/prettier-plugin-liquid": { - "optional": true - }, - "@trivago/prettier-plugin-sort-imports": { - "optional": true - }, - "@zackad/prettier-plugin-twig-melody": { - "optional": true - }, - "prettier-plugin-astro": { - "optional": true - }, - "prettier-plugin-css-order": { - "optional": true - }, - "prettier-plugin-import-sort": { - "optional": true - }, - "prettier-plugin-jsdoc": { - "optional": true - }, - "prettier-plugin-marko": { - "optional": true - }, - "prettier-plugin-organize-attributes": { - "optional": true - }, - "prettier-plugin-organize-imports": { - "optional": true - }, - "prettier-plugin-sort-imports": { - "optional": true - }, - "prettier-plugin-style-order": { - "optional": true - }, - "prettier-plugin-svelte": { - "optional": true - } - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "peer": true, - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-format/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "peer": true - }, - "node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dev": true, - "dependencies": { - "asap": "~2.0.3" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/pvtsutils": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", - "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", - "dev": true, - "dependencies": { - "tslib": "^2.6.1" - } - }, - "node_modules/pvutils": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", - "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", - "dev": true - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz", - "integrity": "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.1", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "globalthis": "^1.0.3", - "which-builtin-type": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", - "dependencies": { - "call-bind": "^1.0.6", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/rehackt": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.1.0.tgz", - "integrity": "sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==", - "peerDependencies": { - "@types/react": "*", - "react": "*" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "react": { - "optional": true - } - } - }, - "node_modules/relay-runtime": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-12.0.0.tgz", - "integrity": "sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.0.0", - "fbjs": "^3.0.0", - "invariant": "^2.2.4" - } - }, - "node_modules/remedial": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", - "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true - }, - "node_modules/remove-trailing-spaces": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz", - "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==", - "dev": true - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/response-iterator": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.6.tgz", - "integrity": "sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.5" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", - "fsevents": "~2.3.2" - } - }, - "node_modules/rrweb-cssom": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", - "dev": true - }, - "node_modules/run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/scuid": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz", - "integrity": "sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==", - "dev": true - }, - "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/signedsource": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/signedsource/-/signedsource-1.0.0.tgz", - "integrity": "sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sponge-case": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz", - "integrity": "sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true - }, - "node_modules/std-env": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", - "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", - "dev": true - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-env-interpolation": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz", - "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==", - "dev": true - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.includes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz", - "integrity": "sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", - "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.7", - "regexp.prototype.flags": "^1.5.2", - "set-function-name": "^2.0.2", - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.0.tgz", - "integrity": "sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==", - "dev": true, - "dependencies": { - "js-tokens": "^9.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strip-literal/node_modules/js-tokens": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.0.tgz", - "integrity": "sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==", - "dev": true - }, - "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", - "dependencies": { - "client-only": "0.0.1" - }, - "engines": { - "node": ">= 12.0.0" - }, - "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/swap-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz", - "integrity": "sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/tailwindcss": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", - "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", - "dev": true, - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.0", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.0", - "lilconfig": "^2.1.0", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.23", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.1", - "postcss-nested": "^6.0.1", - "postcss-selector-parser": "^6.0.11", - "resolve": "^1.22.2", - "sucrase": "^3.32.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/tinybench": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.8.0.tgz", - "integrity": "sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==", - "dev": true - }, - "node_modules/tinypool": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", - "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/title-case": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", - "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "dev": true, - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true - }, - "node_modules/ts-invariant": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", - "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-log": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.5.tgz", - "integrity": "sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA==", - "dev": true - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ua-parser-js": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", - "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], - "engines": { - "node": "*" - } - }, - "node_modules/ufo": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.3.tgz", - "integrity": "sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==", - "dev": true - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true - }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unixify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", - "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", - "dev": true, - "dependencies": { - "normalize-path": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unixify/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dev": true, - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/urlpattern-polyfill": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz", - "integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==", - "dev": true - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/value-or-promise": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", - "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/vite": { - "version": "5.4.7", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", - "integrity": "sha512-5l2zxqMEPVENgvzTuBpHer2awaetimj2BGkhBPdnwKbPNOlHsODU+oiazEZzLK7KhAnOrO+XGYJYn4ZlUhDtDQ==", - "dev": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz", - "integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==", - "dev": true, - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^5.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vitest": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", - "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", - "dev": true, - "dependencies": { - "@vitest/expect": "1.6.0", - "@vitest/runner": "1.6.0", - "@vitest/snapshot": "1.6.0", - "@vitest/spy": "1.6.0", - "@vitest/utils": "1.6.0", - "acorn-walk": "^8.3.2", - "chai": "^4.3.10", - "debug": "^4.3.4", - "execa": "^8.0.1", - "local-pkg": "^0.5.0", - "magic-string": "^0.30.5", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.5.0", - "strip-literal": "^2.0.0", - "tinybench": "^2.5.1", - "tinypool": "^0.8.3", - "vite": "^5.0.0", - "vite-node": "1.6.0", - "why-is-node-running": "^2.2.2" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.6.0", - "@vitest/ui": "1.6.0", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/webcrypto-core": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.0.tgz", - "integrity": "sha512-kR1UQNH8MD42CYuLzvibfakG5Ew5seG85dMMoAM/1LqvckxaF6pUiidLuraIu4V+YCIFabYecUZAW0TuxAoaqw==", - "dev": true, - "dependencies": { - "@peculiar/asn1-schema": "^2.3.8", - "@peculiar/json-schema": "^1.1.12", - "asn1js": "^3.0.1", - "pvtsutils": "^1.3.5", - "tslib": "^2.6.2" - } - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "dev": true, - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-url": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", - "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", - "dev": true, - "dependencies": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", - "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", - "dev": true, - "dependencies": { - "function.prototype.name": "^1.1.5", - "has-tostringtag": "^1.0.0", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.0.2", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/why-is-node-running": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", - "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", - "dev": true, - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", - "dev": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yaml-ast-parser": { - "version": "0.0.43", - "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", - "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zen-observable": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" - }, - "node_modules/zen-observable-ts": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz", - "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==", - "dependencies": { - "zen-observable": "0.8.15" - } - } - } -} diff --git a/{{cookiecutter.project_slug}}/frontend/package.json b/{{cookiecutter.project_slug}}/frontend/package.json deleted file mode 100644 index f106ecfd..00000000 --- a/{{cookiecutter.project_slug}}/frontend/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "{{ cookiecutter.project_name }}", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint-src": "next lint", - "lint-fix": "next lint --fix", - "format": "prettier --write .", - "format-check": "prettier --check .", - "test": "vitest --run", - "test-watch": "vitest", - "typecheck": "tsc --noEmit", - "prepare": "cd .. && husky frontend/.husky", - "codegen": "graphql-codegen" - }, - "dependencies": { - "@apollo/client": "^3.10.8", - "@testing-library/jest-dom": "^6.5.0", - "@testing-library/user-event": "^14.5.2", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "clsx": "^2.1.1", - "deepmerge": "^4.3.1", - "eslint-plugin-unused-imports": "^3.2.0", - "lodash": "^4.17.21", - "next": "14.2.10", - "react": "^18", - "react-dom": "^18" - }, - "devDependencies": { - "@graphql-codegen/cli": "^5.0.2", - "@graphql-codegen/client-preset": "^4.3.2", - "@graphql-typed-document-node/core": "^3.2.0", - "@testing-library/react": "^16.0.0", - "@types/lodash": "^4.17.6", - "@types/node": "20.16.5", - "@types/react": "18.3.5", - "@types/react-dom": "^18", - "@vitejs/plugin-react": "^4.3.1", - "eslint": "^8.57.0", - "eslint-config-next": "14.2.4", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsx-a11y": "^6.9.0", - "eslint-plugin-react": "^7.35.2", - "eslint-plugin-react-hooks": "^4.6.2", - "graphql": "^16.9.0", - "husky": "^9.0.11", - "jsdom": "^24.1.0", - "postcss": "^8", - "prettier": "^3.3.2", - "prettier-plugin-tailwindcss": "^0.6.5", - "tailwindcss": "^3.4.1", - "typescript": "5.6.2", - "vitest": "^1.6.0" - } -} diff --git a/{{cookiecutter.project_slug}}/frontend/pages/404.tsx b/{{cookiecutter.project_slug}}/frontend/pages/404.tsx deleted file mode 100644 index 054afad7..00000000 --- a/{{cookiecutter.project_slug}}/frontend/pages/404.tsx +++ /dev/null @@ -1,8 +0,0 @@ -export default function Custom404() { - return ( - <> - <h1>404 - Page Not Found</h1> - <p>Edit pages/404.tsx</p> - </> - ) -} diff --git a/{{cookiecutter.project_slug}}/frontend/pages/500.tsx b/{{cookiecutter.project_slug}}/frontend/pages/500.tsx deleted file mode 100644 index 79519a66..00000000 --- a/{{cookiecutter.project_slug}}/frontend/pages/500.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Custom500() { - return <h1>500 - Server-side error occurred</h1> -} diff --git a/{{cookiecutter.project_slug}}/frontend/pages/_app.tsx b/{{cookiecutter.project_slug}}/frontend/pages/_app.tsx deleted file mode 100644 index fdb84925..00000000 --- a/{{cookiecutter.project_slug}}/frontend/pages/_app.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { ApolloProvider } from '@apollo/client' -import type { AppProps } from 'next/app' - -import { useApollo } from '../lib/apolloClient' - -import ErrorBoundary from '@/components/ErrorBoundary' -import Layout from '@/components/Layout' -import '@/styles/globals.css' - -export default function App({ Component, pageProps }: AppProps) { - const apolloClient = useApollo(pageProps) - return ( - <ErrorBoundary> - <ApolloProvider client={apolloClient}> - <Layout> - <Component {...pageProps} /> - </Layout> - </ApolloProvider> - </ErrorBoundary> - ) -} diff --git a/{{cookiecutter.project_slug}}/frontend/pages/_document.tsx b/{{cookiecutter.project_slug}}/frontend/pages/_document.tsx deleted file mode 100644 index ee65e53e..00000000 --- a/{{cookiecutter.project_slug}}/frontend/pages/_document.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Html, Head, Main, NextScript } from 'next/document' - -export default function Document() { - return ( - <Html lang='en'> - <Head /> - <body> - <Main /> - <NextScript /> - </body> - </Html> - ) -} diff --git a/{{cookiecutter.project_slug}}/frontend/pages/about.tsx b/{{cookiecutter.project_slug}}/frontend/pages/about.tsx deleted file mode 100644 index 86d934ba..00000000 --- a/{{cookiecutter.project_slug}}/frontend/pages/about.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { useQuery } from '@apollo/client' - -import { GET_ME } from '.' - -import { addApolloState, initializeApollo } from '@/lib/apolloClient' - -export default function About() { - const { loading, error, data } = useQuery(GET_ME) - - if (loading) return <p>Loading...</p> - return ( - <> - <h1>About Page</h1> - <p>This page using Server Side Rendering to fetch User Info</p> - {error ? <p>Error: {error.message}</p> : <p>{data?.me.name}</p>}{' '} - </> - ) -} -export async function getServerSideProps() { - const apolloClient = initializeApollo() - try { - await apolloClient.query({ - query: GET_ME - }) - } catch (error) { - console.log('error', error) - } - return addApolloState(apolloClient, { - props: {} - }) -} diff --git a/{{cookiecutter.project_slug}}/frontend/pages/api/hello.ts b/{{cookiecutter.project_slug}}/frontend/pages/api/hello.ts deleted file mode 100644 index 9bafa6e2..00000000 --- a/{{cookiecutter.project_slug}}/frontend/pages/api/hello.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Next.js API route support: https://nextjs.org/docs/api-routes/introduction -import type { NextApiRequest, NextApiResponse } from 'next' - -type Data = { - name: string -} - -export default function handler(req: NextApiRequest, res: NextApiResponse<Data>) { - res.status(200).json({ name: 'John Doe' }) -} diff --git a/{{cookiecutter.project_slug}}/frontend/pages/index.tsx b/{{cookiecutter.project_slug}}/frontend/pages/index.tsx deleted file mode 100644 index 4c090d26..00000000 --- a/{{cookiecutter.project_slug}}/frontend/pages/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useQuery } from '@apollo/client' - -import { gql } from '@/__generated__' - -export const GET_ME = gql(/* GraphQL */ ` - query Me { - me { - id - name - } - } -`) - -export default function Home() { - const { loading, error, data } = useQuery(GET_ME) - - if (loading) return <p>Loading...</p> - return ( - <> - <h1>Home Page</h1> - <p>This page using Client Side Rendering to fetch User Info</p> - {error ? <p>Error: {error.message}</p> : <p>{data?.me.name}</p>} - </> - ) -} diff --git a/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs b/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs deleted file mode 100644 index b1d7bf47..00000000 --- a/{{cookiecutter.project_slug}}/frontend/postcss.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -/** @type {import('postcss-load-config').Config} */ -const config = { - plugins: { - tailwindcss: {} - } -} - -export default config diff --git a/{{cookiecutter.project_slug}}/frontend/public/favicon.ico b/{{cookiecutter.project_slug}}/frontend/public/favicon.ico deleted file mode 100644 index 718d6fea4835ec2d246af9800eddb7ffb276240c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25931 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 LrJugUA?W`A8`#=m diff --git a/{{cookiecutter.project_slug}}/frontend/public/scaf-logo.png b/{{cookiecutter.project_slug}}/frontend/public/scaf-logo.png deleted file mode 100644 index 521c0d9dc716defcf6d3db7ce3ec491700648f6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47188 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 diff --git a/{{cookiecutter.project_slug}}/frontend/styles/globals.css b/{{cookiecutter.project_slug}}/frontend/styles/globals.css deleted file mode 100644 index b5c61c95..00000000 --- a/{{cookiecutter.project_slug}}/frontend/styles/globals.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/{{cookiecutter.project_slug}}/frontend/tailwind.config.ts b/{{cookiecutter.project_slug}}/frontend/tailwind.config.ts deleted file mode 100644 index f00baee9..00000000 --- a/{{cookiecutter.project_slug}}/frontend/tailwind.config.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Config } from 'tailwindcss' - -const config: Config = { - content: [ - './pages/**/*.{js,ts,jsx,tsx,mdx}', - './components/**/*.{js,ts,jsx,tsx,mdx}', - './app/**/*.{js,ts,jsx,tsx,mdx}' - ], - plugins: [] -} -export default config diff --git a/{{cookiecutter.project_slug}}/frontend/tsconfig.json b/{{cookiecutter.project_slug}}/frontend/tsconfig.json deleted file mode 100644 index 649790e5..00000000 --- a/{{cookiecutter.project_slug}}/frontend/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "paths": { - "@/*": ["./*"] - } - }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], - "exclude": ["node_modules"] -} diff --git a/{{cookiecutter.project_slug}}/frontend/utils/test-utils.tsx b/{{cookiecutter.project_slug}}/frontend/utils/test-utils.tsx deleted file mode 100644 index 6c79c0ce..00000000 --- a/{{cookiecutter.project_slug}}/frontend/utils/test-utils.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' -import { render } from '@testing-library/react' -import { MockedProvider, MockedResponse } from '@apollo/client/testing' - -type Options = { - mocks?: MockedResponse[] -} -const renderWithProviders = (ui: React.ReactElement, options: Options = {}) => { - render( - <MockedProvider mocks={options.mocks} addTypename={false}> - {ui} - </MockedProvider> - ) -} - -export * from '@testing-library/react' -export { renderWithProviders as render } -export { userEvent } from '@testing-library/user-event' diff --git a/{{cookiecutter.project_slug}}/frontend/vitest.config.ts b/{{cookiecutter.project_slug}}/frontend/vitest.config.ts deleted file mode 100644 index 79b8b21a..00000000 --- a/{{cookiecutter.project_slug}}/frontend/vitest.config.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { defineConfig } from 'vitest/config' -import react from '@vitejs/plugin-react' -import { fileURLToPath } from 'node:url' - -export default defineConfig({ - plugins: [react()], - test: { - environment: 'jsdom', - setupFiles: ['./vitest.setup.ts'] - }, - resolve: { - alias: { - '@': fileURLToPath(new URL('./', import.meta.url)) - } - } -}) diff --git a/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts b/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts deleted file mode 100644 index 10234f43..00000000 --- a/{{cookiecutter.project_slug}}/frontend/vitest.setup.ts +++ /dev/null @@ -1,3 +0,0 @@ -/// <reference types="vitest" /> - -import '@testing-library/jest-dom/vitest' diff --git a/{{cookiecutter.project_slug}}/k8s/_monitoring/django-logs-table.yaml b/{{cookiecutter.project_slug}}/k8s/_monitoring/django-logs-table.yaml deleted file mode 100644 index 581ead00..00000000 --- a/{{cookiecutter.project_slug}}/k8s/_monitoring/django-logs-table.yaml +++ /dev/null @@ -1,190 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - grafana_dashboard: "1" - name: django-logs-table - namespace: monitoring -data: - django-logs-table.json: |- - { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 33, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "loki", - "uid": "P8E80F9AEF21F6940" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 1, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "10.1.1", - "targets": [ - { - "datasource": { - "type": "loki", - "uid": "P8E80F9AEF21F6940" - }, - "editorMode": "builder", - "expr": "{namespace=\"default\", container=\"django\"} |= ``", - "queryType": "range", - "refId": "A" - } - ], - "title": "Django Logs Table", - "type": "table" - }, - { - "datasource": { - "type": "loki", - "uid": "P8E80F9AEF21F6940" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 2, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": [ - "sum" - ], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "10.1.1", - "targets": [ - { - "datasource": { - "type": "loki", - "uid": "P8E80F9AEF21F6940" - }, - "editorMode": "builder", - "expr": "{namespace=\"default\", container=\"postgres\"} |= ``", - "queryType": "range", - "refId": "A" - } - ], - "title": "Postgres Logs Table", - "type": "table" - } - ], - "refresh": "", - "schemaVersion": 38, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Django", - "uid": "1693997350", - "version": 3, - "weekStart": "" - } diff --git a/{{cookiecutter.project_slug}}/k8s/_monitoring/loki-stack-values.yaml b/{{cookiecutter.project_slug}}/k8s/_monitoring/loki-stack-values.yaml deleted file mode 100644 index 813644a6..00000000 --- a/{{cookiecutter.project_slug}}/k8s/_monitoring/loki-stack-values.yaml +++ /dev/null @@ -1,33 +0,0 @@ -loki: - env: - - name: AWS_ACCESS_KEY_ID - valueFrom: - secretKeyRef: - name: iam-loki-s3 - key: AWS_ACCESS_KEY_ID - - name: AWS_SECRET_ACCESS_KEY - valueFrom: - secretKeyRef: - name: iam-loki-s3 - key: AWS_SECRET_ACCESS_KEY - config: - schema_config: - configs: - - from: 2021-05-12 - store: boltdb-shipper - object_store: s3 - schema: v11 - index: - prefix: loki_index_ - period: 24h - storage_config: - aws: - s3: s3://{{ cookiecutter.aws_region }}/{{ cookiecutter.project_dash }}-loki-index-bucket - s3forcepathstyle: true - bucketnames: {{ cookiecutter.project_dash }}-loki-index-bucket - region: {{ cookiecutter.aws_region }} - insecure: false - sse_encryption: false - boltdb_shipper: - shared_store: s3 - cache_ttl: 24h diff --git a/{{cookiecutter.project_slug}}/k8s/argocd/README.md b/{{cookiecutter.project_slug}}/k8s/argocd/README.md deleted file mode 100644 index 28b7d95a..00000000 --- a/{{cookiecutter.project_slug}}/k8s/argocd/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Kubernetes Control Plane - -## ArgoCD - -An ArgoCD application will automate your kubernetes deployments. - -Install [ArgoCD CLI](https://argo-cd.readthedocs.io/en/stable/cli_installation/). - -Log in to your ArgoCD dashboard, eg - - $ argocd login argocd.sixfeetup.com - -Find your cluster context (set your KUBECONFIG file if neccessary) - - $ kubectl config get-contexts -o name - -Add your cluster to ArgoCD. This will also output the `CLUSTER_IP` you will use in the application. - - $ argocd cluster add {{ cookiecutter.project_slug }}-ec2-cluster - -### Creating the ArgoCD application manifests - -Export the cluster IP from ArgoCD to your environment - - $ export CLUSTER_IP=CLUSTER_IP - -Create a deploy key for your repository export it to your environment as `SSH_PRIVATE_KEY`. - - $ export SSH_PRIVATE_KEY=DEPLOY_KEY - -Export your repository url to your environment - - $ export REPO_URL=PROJECT_REPOSITORY - -Create the `application.yaml` manifest and `repocred.yaml` secret and seal it - - $ make argocd-app - -If you are working in the SFU environment move your application and repocreds manifest to `sixfeetup/controlplane.git/argocd/applications/{{ cookiecutter.project_slug }}/` - -Apply the manifests - - $ kubectl apply -f argocd/applications/{{ cookiecutter.project_slug }} - -Your ArgoCD application should be visible on the ArgoCD dashboard. Check the repository and cluster connection. diff --git a/{{cookiecutter.project_slug}}/k8s/base/app.configmap.yaml b/{{cookiecutter.project_slug}}/k8s/base/app.configmap.yaml deleted file mode 100644 index 6961bb72..00000000 --- a/{{cookiecutter.project_slug}}/k8s/base/app.configmap.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: app-config -data: - DJANGO_DEBUG: "False" - DEBUGGER_IDE: "" # "pycharm" or empty - USE_DOCKER: "yes" - DJANGO_ADMIN_URL: "admin/" - DJANGO_SETTINGS_MODULE: "config.settings.local" - DJANGO_SECRET_KEY: "CHANGEME" - DJANGO_ALLOWED_HOSTS: "localhost,127.0.0.1,backend,.{{ cookiecutter.domain_name }}" - DJANGO_CSRF_TRUSTED_ORIGINS: "http://localhost,https://{{ cookiecutter.domain_name }}" - DJANGO_SECURE_SSL_REDIRECT: "False" - PGDATA: "/var/lib/postgresql/data/pgdata" - POSTGRES_DB: "{{ cookiecutter.project_slug }}" - POSTGRES_USER: "{{ cookiecutter.project_slug }}" - REDIS_URL: "redis://redis:6379/1" -{%- if cookiecutter.mail_service == 'Mailgun' %} - MAILGUN_DOMAIN: "{{ cookiecutter.domain_name }}" - MAILGUN_API_URL: "https://api.mailgun.net/v3"{%- endif %} -{%- if cookiecutter.use_celery == "y" %} - CELERY_BROKER_URL: "redis://redis:6379/0" - FLOWER_BROKER_URL: "redis://redis:6379/0" - FLOWER_ADDRESS: "0.0.0.0" - FLOWER_PORT: "5555"{%- endif %} -{%- if cookiecutter._challenge == "y" %} - # Scaf challenge settings - CHALLENGE_SESSION_ID: __CHALLENGE_SESSION_ID__ - CHALLENGE_JWT_TOKEN: __CHALLENGE_JWT_TOKEN__ - CHALLENGE_BASE_URL: __CHALLENGE_BASE_URL__ -{%- endif %} - # S3 storage access - DJANGO_AWS_REGION_NAME: "{{ cookiecutter.aws_region }}" - DJANGO_AWS_STORAGE_BUCKET_NAME: "CHANGEME_S3_BUCKET_NAME" -{% if cookiecutter.use_sentry == 'y' %} - SENTRY_DSN_BACKEND: "" - ENVIRONMENT: "dev" - VITE_SENTRY_DSN_FRONTEND: "" - VITE_ENVIRONMENT: "dev"{% endif %} diff --git a/{{cookiecutter.project_slug}}/k8s/base/celery.yaml b/{{cookiecutter.project_slug}}/k8s/base/celery.yaml deleted file mode 100644 index 4c1d206d..00000000 --- a/{{cookiecutter.project_slug}}/k8s/base/celery.yaml +++ /dev/null @@ -1,41 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: celery - labels: - app: celery -spec: - replicas: 1 - selector: - matchLabels: - app: celery - template: - metadata: - labels: - app: celery - spec: - containers: - - name: celeryworker - image: backend:latest - command: ["celery", "-A", "{{ cookiecutter.project_slug }}", "worker", "-E", "-l", "info"] - envFrom: - - configMapRef: - name: app-config - - secretRef: - name: secrets-config - - name: celerybeat - image: backend:latest - command: ["celery", "-A", "{{ cookiecutter.project_slug }}", "beat"] - envFrom: - - configMapRef: - name: app-config - - secretRef: - name: secrets-config - - name: flower - image: backend:latest - command: ["celery", "-A", "{{ cookiecutter.project_slug }}", "flower"] - envFrom: - - configMapRef: - name: app-config - - secretRef: - name: secrets-config diff --git a/{{cookiecutter.project_slug}}/k8s/base/django.yaml b/{{cookiecutter.project_slug}}/k8s/base/django.yaml deleted file mode 100644 index 8c1ee07a..00000000 --- a/{{cookiecutter.project_slug}}/k8s/base/django.yaml +++ /dev/null @@ -1,82 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: backend - labels: - app: backend -spec: - type: ClusterIP - selector: - app: backend - ports: - - port: 8000 - targetPort: http-server ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: backend - labels: - app: backend -spec: - replicas: 1 - selector: - matchLabels: - app: backend - template: - metadata: - labels: - app: backend - spec: - containers: - - name: backend - image: backend:latest - command: ["python", "manage.py", "runserver", "0.0.0.0:8000"] - ports: - - name: http-server - containerPort: 8000 - envFrom: - - configMapRef: - name: app-config - - secretRef: - name: secrets-config - livenessProbe: - httpGet: - path: /healthz - port: 8000 - httpHeaders: - - name: Host - value: localhost - initialDelaySeconds: 29 - periodSeconds: 29 - timeoutSeconds: 2 - failureThreshold: 3 - terminationGracePeriodSeconds: 60 - readinessProbe: - httpGet: - path: /readiness - port: 8000 - httpHeaders: - - name: Host - value: localhost - initialDelaySeconds: 31 - periodSeconds: 31 - timeoutSeconds: 3 - successThreshold: 1 - initContainers: - - name: check-db-ready - image: postgres:16 - command: [ - "sh", - "-c", - "until pg_isready -h $(POSTGRES_HOST); - do echo waiting for postgres; sleep 2; done;", - ] - - name: backend-migration - image: backend:latest - command: ["python", "manage.py", "migrate"] - envFrom: - - configMapRef: - name: app-config - - secretRef: - name: secrets-config diff --git a/{{cookiecutter.project_slug}}/k8s/base/flower.yaml b/{{cookiecutter.project_slug}}/k8s/base/flower.yaml deleted file mode 100644 index 09affb62..00000000 --- a/{{cookiecutter.project_slug}}/k8s/base/flower.yaml +++ /dev/null @@ -1,31 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: flower - labels: - app: {{ cookiecutter.project_slug }} -spec: - replicas: 1 - selector: - matchLabels: - app: {{ cookiecutter.project_slug }} - template: - metadata: - labels: - app: {{ cookiecutter.project_slug }} - spec: - containers: - - name: flower - image: {{ cookiecutter.project_slug }}_local_django:latest - command: ["celery", "-A", "{{ cookiecutter.project_slug }}", "flower"] - envFrom: - - configMapRef: - name: django-config - initContainers: - - name: celery-check-workers-ready - image: {{ cookiecutter.project_slug }}_local_django:latest - command: - ['sh', '-c', 'until celery -A {{ cookiecutter.project_slug }} inspect ping; do echo Waiting for Celery workers to be ready; sleep 5; done'] - envFrom: - - configMapRef: - name: django-config diff --git a/{{cookiecutter.project_slug}}/k8s/base/frontend.yaml b/{{cookiecutter.project_slug}}/k8s/base/frontend.yaml deleted file mode 100644 index b3dcd151..00000000 --- a/{{cookiecutter.project_slug}}/k8s/base/frontend.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: frontend - labels: - app: frontend -spec: - type: ClusterIP - selector: - app: frontend - ports: - - port: 3000 - targetPort: http-server ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: frontend - labels: - app: frontend -spec: - replicas: 1 - selector: - matchLabels: - app: frontend - template: - metadata: - labels: - app: frontend - spec: - containers: - - name: frontend - image: frontend:latest - ports: - - name: http-server - containerPort: 3000 - env: - - name: PORT - value: "3000" - - name: DJANGO_ADDRESS - value: backend:8000 - envFrom: - - configMapRef: - name: app-config - - secretRef: - name: secrets-config diff --git a/{{cookiecutter.project_slug}}/k8s/base/ingress.yaml b/{{cookiecutter.project_slug}}/k8s/base/ingress.yaml deleted file mode 100644 index d6e93f87..00000000 --- a/{{cookiecutter.project_slug}}/k8s/base/ingress.yaml +++ /dev/null @@ -1,65 +0,0 @@ -{% if cookiecutter.create_nextjs_frontend == "y" %} -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: frontend-ingress - annotations: - cert-manager.io/issuer: letsencrypt-staging -spec: - entryPoints: - - websecure - routes: - - kind: Rule - match: {{ cookiecutter.project_slug }}.local - priority: 10 - services: - - name: frontend - port: 3000 - tls: - certResolver: letsencrypt ---- -{% endif %} -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: backend-ingress - annotations: - cert-manager.io/issuer: letsencrypt-staging -spec: - entryPoints: - - websecure - routes: - - kind: Rule - match: k8s.{{ cookiecutter.project_slug }}.local - priority: 10 - services: - - name: backend - port: 8000 - tls: - certResolver: letsencrypt ---- -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: http-to-https-redirect -spec: - entryPoints: - - web - routes: - - kind: Rule - match: PathPrefix(`/`) - priority: 1 - middlewares: - - name: redirect-to-https - services: - - kind: TraefikService - name: noop@internal ---- -apiVersion: traefik.io/v1alpha1 -kind: Middleware -metadata: - name: redirect-to-https -spec: - redirectScheme: - scheme: https - permanent: true diff --git a/{{cookiecutter.project_slug}}/k8s/base/kustomization.yaml b/{{cookiecutter.project_slug}}/k8s/base/kustomization.yaml deleted file mode 100644 index 87da76ee..00000000 --- a/{{cookiecutter.project_slug}}/k8s/base/kustomization.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- ./app.configmap.yaml -- ./django.yaml -{% if cookiecutter.create_nextjs_frontend == "y" %} -- ./frontend.yaml{% endif %} -- ./redis.yaml -{%- if cookiecutter.use_celery == "y" %} -- ./celery.yaml{%- endif %} diff --git a/{{cookiecutter.project_slug}}/k8s/base/redis.yaml b/{{cookiecutter.project_slug}}/k8s/base/redis.yaml deleted file mode 100644 index 0e0900c8..00000000 --- a/{{cookiecutter.project_slug}}/k8s/base/redis.yaml +++ /dev/null @@ -1,36 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: redis - labels: - app: redis -spec: - type: ClusterIP - selector: - app: redis - ports: - - port: 6379 - targetPort: redis-server ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: redis - labels: - app: redis -spec: - replicas: 1 - selector: - matchLabels: - app: redis - template: - metadata: - labels: - app: redis - spec: - containers: - - name: redis - image: redis:6.0.5 - ports: - - name: redis-server - containerPort: 6379 diff --git a/{{cookiecutter.project_slug}}/k8s/local/kustomization.yaml b/{{cookiecutter.project_slug}}/k8s/local/kustomization.yaml deleted file mode 100644 index b3196a0c..00000000 --- a/{{cookiecutter.project_slug}}/k8s/local/kustomization.yaml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: -- ../base -- ../mailhog -- ./postgres.yaml -- ./secrets.yaml - -patches: -- patch: |- - - op: add - path: /spec/template/spec/initContainers/0/env - value: - - name: POSTGRES_HOST - value: postgres - - op: replace - path: /spec/template/spec/containers/0/livenessProbe - value: null - - op: replace - path: /spec/template/spec/containers/0/readinessProbe - value: null - target: - kind: Deployment - name: backend -- patch: |- - - op: add - path: /spec/template/spec/containers/0/env - value: - - name: DOCKER_GATEWAY_IP # used for debugger to reach out to host machine - value: "172.17.0.1" - target: - kind: Deployment - name: backend diff --git a/{{cookiecutter.project_slug}}/k8s/local/postgres.yaml b/{{cookiecutter.project_slug}}/k8s/local/postgres.yaml deleted file mode 100644 index a42701d6..00000000 --- a/{{cookiecutter.project_slug}}/k8s/local/postgres.yaml +++ /dev/null @@ -1,78 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: postgres - labels: - app: postgres -spec: - ports: - - port: 5432 - targetPort: 5432 - selector: - app: postgres ---- -apiVersion: apps/v1 -kind: StatefulSet -metadata: - name: postgres - labels: - app: postgres -spec: - serviceName: postgres - replicas: 1 - selector: - matchLabels: - app: postgres - template: - metadata: - labels: - app: postgres - spec: - containers: - - name: postgres - image: postgres:16 - ports: - - containerPort: 5432 - envFrom: - - configMapRef: - name: app-config - - secretRef: - name: secrets-config - volumeMounts: - - name: postgres-volume-mount - mountPath: /var/lib/postgresql/data - # readinessProbe: - # exec: - # command: - # - bash - # - "-c" - # - "psql -U$POSTGRES_USER -d$POSTGRES_DB -c 'SELECT 1'" - # initialDelaySeconds: 15 - # timeoutSeconds: 2 - # livenessProbe: - # exec: - # command: - # - bash - # - "-c" - # - "psql -U$POSTGRES_USER -d$POSTGRES_DB -c 'SELECT 1'" - # initialDelaySeconds: 15 - # timeoutSeconds: 2 - volumes: - - name: postgres-volume-mount - persistentVolumeClaim: - claimName: postgres-pvc ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - annotations: - tilt.dev/down-policy: keep - name: postgres-pvc - labels: - type: local -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 500Mi diff --git a/{{cookiecutter.project_slug}}/k8s/local/secrets.yaml b/{{cookiecutter.project_slug}}/k8s/local/secrets.yaml deleted file mode 100644 index 3c613768..00000000 --- a/{{cookiecutter.project_slug}}/k8s/local/secrets.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -stringData: - POSTGRES_PASSWORD: __POSTGRES_PASSWORD__ - DATABASE_URL: postgresql://{{ cookiecutter.project_slug }}:__POSTGRES_PASSWORD__@postgres/{{ cookiecutter.project_slug }} - DJANGO_SECRET_KEY: __DJANGO_SECRET_KEY__ -kind: Secret -metadata: - name: secrets-config -type: Opaque diff --git a/{{cookiecutter.project_slug}}/k8s/mailhog/kustomization.yaml b/{{cookiecutter.project_slug}}/k8s/mailhog/kustomization.yaml deleted file mode 100644 index a4a1a56c..00000000 --- a/{{cookiecutter.project_slug}}/k8s/mailhog/kustomization.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization - -resources: - - mailhog.yaml diff --git a/{{cookiecutter.project_slug}}/k8s/mailhog/mailhog.yaml b/{{cookiecutter.project_slug}}/k8s/mailhog/mailhog.yaml deleted file mode 100644 index f3f35171..00000000 --- a/{{cookiecutter.project_slug}}/k8s/mailhog/mailhog.yaml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mailhog - labels: - app: mailhog -spec: - type: ClusterIP - selector: - app: mailhog - ports: - - port: 8025 - targetPort: smtp-server-ui - name: smtp-server-ui - - port: 1025 - targetPort: smtp-server - name: smtp-server ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mailhog - labels: - app: mailhog -spec: - replicas: 1 - selector: - matchLabels: - app: mailhog - template: - metadata: - labels: - app: mailhog - spec: - containers: - - name: mailhog - image: mailhog/mailhog:v1.0.0 - ports: - - name: smtp-server-ui - containerPort: 8025 - - name: smtp-server - containerPort: 1025 diff --git a/{{cookiecutter.project_slug}}/k8s/prod/kustomization.yaml b/{{cookiecutter.project_slug}}/k8s/prod/kustomization.yaml deleted file mode 100644 index 456b9be5..00000000 --- a/{{cookiecutter.project_slug}}/k8s/prod/kustomization.yaml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -namespace: {{ cookiecutter.project_dash }}-prod - -resources: - - ../sandbox - - secrets.yaml - -patches: -- target: - kind: SealedSecret - name: secrets-config - path: secrets.yaml -- patch: |- - - op: replace - path: /spec/issuerRef/name - value: letsencrypt-prod - - op: replace - path: /spec/dnsNames - value: - - api.{{ cookiecutter.domain_name }} - - k8s.{{ cookiecutter.domain_name }} - target: - kind: Certificate - name: cluster-cert -- patch: |- - - op: replace - path: /metadata/annotations/cert-manager.io~1cluster-issuer - value: letsencrypt-prod - - op: replace - path: /spec/routes/0/match - value: Host(`api.{{ cookiecutter.domain_name }}`) - target: - kind: IngressRoute - name: backend-ingress -- patch: |- - - op: replace - path: /metadata/annotations/cert-manager.io~1cluster-issuer - value: letsencrypt-prod - - op: replace - path: /spec/routes/0/match - value: Host(`k8s.{{ cookiecutter.domain_name }}`) - target: - kind: IngressRoute - name: k8s-ingress - -configMapGenerator: - - name: app-config - behavior: merge - literals: - - ENVIRONMENT="production" - - DJANGO_SETTINGS_MODULE="config.settings.production" - - DJANGO_CSRF_TRUSTED_ORIGINS="https://{{ cookiecutter.domain_name }}" - - AWS_S3_CUSTOM_DOMAIN="{{ cookiecutter.domain_name }}" - -images: - - name: {{ cookiecutter.aws_account_id }}.dkr.ecr.{{ cookiecutter.aws_region }}.amazonaws.com/{{ cookiecutter.project_dash }}-sandbox-backend - newName: {{ cookiecutter.aws_account_id }}.dkr.ecr.{{ cookiecutter.aws_region }}.amazonaws.com/{{ cookiecutter.project_dash }}-backend - newTag: latest -{% if cookiecutter.create_nextjs_frontend == "y" %} - - name: {{ cookiecutter.aws_account_id }}.dkr.ecr.{{ cookiecutter.aws_region }}.amazonaws.com/{{ cookiecutter.project_dash }}-sandbox-frontend - newName: {{ cookiecutter.aws_account_id }}.dkr.ecr.{{ cookiecutter.aws_region }}.amazonaws.com/{{ cookiecutter.project_dash }}-frontend - newTag: latest{% endif %} diff --git a/{{cookiecutter.project_slug}}/k8s/sandbox/certificate.yaml b/{{cookiecutter.project_slug}}/k8s/sandbox/certificate.yaml deleted file mode 100644 index b639da40..00000000 --- a/{{cookiecutter.project_slug}}/k8s/sandbox/certificate.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: cluster-cert -spec: - secretName: cluster-cert-tls - issuerRef: - name: letsencrypt-staging - kind: ClusterIssuer - dnsNames: - - api.sandbox.{{ cookiecutter.domain_name }} - - k8s.sandbox.{{ cookiecutter.domain_name }} diff --git a/{{cookiecutter.project_slug}}/k8s/sandbox/ingress-route.yaml b/{{cookiecutter.project_slug}}/k8s/sandbox/ingress-route.yaml deleted file mode 100644 index dee22479..00000000 --- a/{{cookiecutter.project_slug}}/k8s/sandbox/ingress-route.yaml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: backend-ingress - annotations: - cert-manager.io/cluster-issuer: letsencrypt-staging -spec: - entryPoints: - - websecure - routes: - - kind: Rule - match: Host(`api.sandbox.{{ cookiecutter.domain_name }}`) - priority: 10 - services: - - name: backend - port: 8000 - tls: - secretName: cluster-cert-tls ---- -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: k8s-ingress - annotations: - cert-manager.io/cluster-issuer: letsencrypt-staging -spec: - entryPoints: - - websecure - routes: - - kind: Rule - match: Host(`k8s.sandbox.{{ cookiecutter.domain_name }}`) - priority: 10 - services: - - name: backend - port: 8000 - tls: - secretName: cluster-cert-tls ---- -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: http-to-https-redirect -spec: - entryPoints: - - web - routes: - - kind: Rule - match: PathPrefix(`/`) - priority: 1 - middlewares: - - name: redirect-to-https - services: - - kind: TraefikService - name: noop@internal ---- -apiVersion: traefik.io/v1alpha1 -kind: Middleware -metadata: - name: redirect-to-https -spec: - redirectScheme: - scheme: https - permanent: true diff --git a/{{cookiecutter.project_slug}}/k8s/sandbox/kustomization.yaml b/{{cookiecutter.project_slug}}/k8s/sandbox/kustomization.yaml deleted file mode 100644 index a8135c20..00000000 --- a/{{cookiecutter.project_slug}}/k8s/sandbox/kustomization.yaml +++ /dev/null @@ -1,85 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -namespace: {{ cookiecutter.project_slug }}-sandbox - -resources: - - ../base - - certificate.yaml - - ingress-route.yaml - - postgres.cnpg.yaml - - secrets.yaml - -patches: -- patch: |- - - op: replace - path: /spec/template/spec/containers/0/command - value: ["daphne"] - - op: replace - path: /spec/template/spec/containers/0/args - value: ["--bind", "0.0.0.0", "--port", "8000", "--ping-interval", "15", "--ping-timeout", "5", "config.asgi:application"] - - op: add - path: /spec/template/spec/imagePullSecrets - value: - - name: regcred - - op: add - path: /spec/template/spec/initContainers/0/env - value: - - name: POSTGRES_HOST - valueFrom: - secretKeyRef: - name: postgres-app - key: host - - op: replace - path: /spec/template/spec/initContainers/0/command - value: ["sh", "-c", "until pg_isready -h $(POSTGRES_HOST); do echo waiting for postgres; sleep 2; done;"] - - op: add - path: /spec/template/spec/initContainers/1/env - value: - - name: DATABASE_URL - valueFrom: - secretKeyRef: - name: postgres-app - key: uri - - op: add - path: /spec/template/spec/containers/0/env - value: - - name: POSTGRES_HOST - valueFrom: - secretKeyRef: - name: postgres-app - key: host - - name: DATABASE_URL - valueFrom: - secretKeyRef: - name: postgres-app - key: uri - target: - kind: Deployment - name: backend -{% if cookiecutter.create_nextjs_frontend == "y" %} -- patch: |- - - op: add - path: /spec/template/spec/imagePullSecrets - value: - - name: regcred - target: - kind: Deployment - name: frontend{% endif %} - -configMapGenerator: - - name: app-config - behavior: merge - literals: - - ENVIRONMENT="sandbox" - - DJANGO_SETTINGS_MODULE="config.settings.production" - - DJANGO_CSRF_TRUSTED_ORIGINS="https://sandbox.{{ cookiecutter.domain_name }}" - - AWS_S3_CUSTOM_DOMAIN="sandbox.{{ cookiecutter.domain_name }}" - -images: - - name: backend - newName: {{ cookiecutter.aws_account_id }}.dkr.ecr.{{ cookiecutter.aws_region }}.amazonaws.com/{{ cookiecutter.project_dash }}-sandbox-backend - newTag: latest -{% if cookiecutter.create_nextjs_frontend == "y" %} - - name: frontend - newName: {{ cookiecutter.aws_account_id }}.dkr.ecr.{{ cookiecutter.aws_region }}.amazonaws.com/{{ cookiecutter.project_dash }}-sandbox-frontend - newTag: latest{% endif %} diff --git a/{{cookiecutter.project_slug}}/k8s/sandbox/postgres.cnpg.yaml b/{{cookiecutter.project_slug}}/k8s/sandbox/postgres.cnpg.yaml deleted file mode 100644 index f713ba22..00000000 --- a/{{cookiecutter.project_slug}}/k8s/sandbox/postgres.cnpg.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: postgresql.cnpg.io/v1 -kind: Cluster -metadata: - name: postgres - labels: - app: postgres -spec: - instances: 1 - envFrom: - - configMapRef: - name: app-config - primaryUpdateStrategy: unsupervised - storage: - size: 2Gi diff --git a/{{cookiecutter.project_slug}}/k8s/templates/secrets.yaml.template b/{{cookiecutter.project_slug}}/k8s/templates/secrets.yaml.template deleted file mode 100644 index b0bf90d3..00000000 --- a/{{cookiecutter.project_slug}}/k8s/templates/secrets.yaml.template +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -stringData: - AWS_S3_ACCESS_KEY_ID: $AWS_S3_ACCESS_KEY_ID - AWS_S3_SECRET_ACCESS_KEY: $AWS_S3_SECRET_ACCESS_KEY -{%- if cookiecutter.mail_service == 'Amazon SES' %} - AWS_SES_ACCESS_KEY_ID: $AWS_SES_ACCESS_KEY_ID - AWS_SES_SECRET_ACCESS_KEY: $AWS_SES_SECRET_ACCESS_KEY{%- endif %} - DJANGO_SECRET_KEY: $DJANGO_SECRET_KEY -{%- if cookiecutter.mail_service == 'Mailgun' %} - MAILGUN_API_KEY: op://{{ cookiecutter.project_name }}/$ENVIRONMENT secrets/MAILGUN_API_KEY"{%- endif %} - -kind: Secret -metadata: - name: secrets-config -type: Opaque diff --git a/{{cookiecutter.project_slug}}/mkdocs.yml b/{{cookiecutter.project_slug}}/mkdocs.yml deleted file mode 100644 index dcf9b3af..00000000 --- a/{{cookiecutter.project_slug}}/mkdocs.yml +++ /dev/null @@ -1,43 +0,0 @@ -site_name: {{ cookiecutter.project_name }} - -plugins: - - search: - separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])' - - mermaid2: - version: '11.4.1' - -theme: - name: material - palette: - - media: "(prefers-color-scheme)" - toggle: - icon: material/link - name: Switch to light mode - - media: "(prefers-color-scheme: light)" - scheme: default - primary: indigo - accent: indigo - toggle: - icon: material/toggle-switch - name: Switch to dark mode - - media: "(prefers-color-scheme: dark)" - scheme: slate - primary: black - accent: indigo - toggle: - icon: material/toggle-switch-off - name: Switch to system preference - font: - text: Roboto - code: Roboto Mono - -markdown_extensions: - - attr_list - - pymdownx.emoji: - emoji_index: !!python/name:material.extensions.emoji.twemoji - emoji_generator: !!python/name:material.extensions.emoji.to_svg - - pymdownx.superfences: - custom_fences: - - name: mermaid - class: mermaid - format: !!python/name:pymdownx.superfences.fence_code_format diff --git a/{{cookiecutter.project_slug}}/terraform/.gitignore b/{{cookiecutter.project_slug}}/terraform/.gitignore deleted file mode 100644 index 6e840fec..00000000 --- a/{{cookiecutter.project_slug}}/terraform/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -talosconfig -kubeconfig -repocreds.yaml -tfplan.out diff --git a/{{cookiecutter.project_slug}}/terraform/README.md b/{{cookiecutter.project_slug}}/terraform/README.md deleted file mode 100644 index 06d53180..00000000 --- a/{{cookiecutter.project_slug}}/terraform/README.md +++ /dev/null @@ -1,165 +0,0 @@ -# Terraform - -This directory contains the Terraform configurations for the Scaf project. The -configurations are organized into several directories, each serving a specific -purpose. Below is a brief overview of each directory and instructions on how to -run the Terraform configurations. - -## Directory Structure - -- **bootstrap**: Bootstraps the Terraform state in an S3 bucket and a DynamoDB - table. This configuration contains the states for all environments and only - needs to be run once. - -- **github**: Sets up a GitHub OIDC provider to allow GitHub to push container - images to ECR repositories. - -- **modules**: Contains a base module that is used by all environments. - -- **prod**: Contains the configuration for the production environment. - -- **sandbox**: Contains the configuration for the sandbox environment. - -- **staging**: Contains the configuration for the staging environment. - -## Setup Instructions - -### Step 1: AWS Authentication - -Ensure that you have installed AWS CLI version 2, as AWS SSO support is only -available in version 2 and above. Create a new AWS profile in `~/.aws/config`. -Here's an example of the `~/.aws/config` profile: - -``` -[profile scaf] -sso_start_url = https://sixfeetup.awsapps.com/start -sso_region = us-east-1 -sso_account_id = <replace with your AWS account id> -sso_role_name = admin -region = us-east-1 -output = json -``` - -Note the `sso_role_name` setting above. Make sure to use a role that provides -you with the necessary permissions to deploy infrastructure on your AWS account. - -Export the `AWS_PROFILE` environment variable and continue logging in: - -``` -$ export AWS_PROFILE=scaf -$ aws sso login -``` - -This should open your browser, allowing you to sign in to your AWS account. Upon -successful login, you will see a message to confirm it: - -``` -Successfully logged into Start URL: https://sixfeetup.awsapps.com/start -``` - -### Step 2: Bootstrap - -The first step is to bootstrap the Terraform state. This involves creating an S3 -bucket and a DynamoDB table to manage the state and locking. - -1. Navigate to the `bootstrap` directory: - - ```bash - cd bootstrap - ``` - -2. Initialize the Terraform configuration: - - ```bash - terraform init - ``` - -3. Plan the Terraform configuration: - - ```bash - terraform plan -out="tfplan.out" - ``` - -4. Apply the Terraform configuration: - ```bash - terraform apply tfplan.out - ``` - -### Step 3: GitHub OIDC Provider - -After bootstrapping the state, the next step is to set up the GitHub OIDC -provider. - -1. Navigate to the `github` directory: - - ```bash - cd ../github - ``` - -2. Initialize the Terraform configuration: - - ```bash - terraform init - ``` - -3. Plan the Terraform configuration: - - ```bash - terraform plan -out="tfplan.out" - ``` - -4. Apply the Terraform configuration: - ```bash - terraform apply tfplan.out - ``` - -### Step 4: Environment Configurations - -The final step is to set up the respective environment configurations (prod, -sandbox, staging). - -1. Navigate to the desired environment directory (e.g., `prod`, `sandbox`, - `staging`): - - ```bash - cd ../<environment> - ``` - -2. Initialize the Terraform configuration: - - ```bash - terraform init - ``` - -3. Restrict the IPs allowed to manage the cluster. Edit - `<environment>/cluster.tf` and set the following variables: - - ``` - admin_allowed_ips = "10.0.0.1/32,10.0.0.2/32" - ``` - -4. Plan the Terraform configuration: - - ```bash - terraform plan -out="tfplan.out" - ``` - -5. Apply the Terraform configuration: - ```bash - terraform apply tfplan.out - ``` - -## Summary - -The order of operations is critical for the correct setup of the Terraform -configurations: - -1. Bootstrap the Terraform state (`bootstrap` directory). -2. Set up the GitHub OIDC provider (`github` directory). -3. Configure the desired environment (`prod`, `sandbox`, or `staging` directory). - -Each step involves running `terraform init`, `terraform plan -out="tfplan.out"`, -and `terraform apply tfplan.out`. - -Following these steps ensures that your infrastructure is set up correctly and -efficiently. diff --git a/{{cookiecutter.project_slug}}/terraform/bootstrap/init.tf b/{{cookiecutter.project_slug}}/terraform/bootstrap/init.tf deleted file mode 100644 index e3bbd7a7..00000000 --- a/{{cookiecutter.project_slug}}/terraform/bootstrap/init.tf +++ /dev/null @@ -1,46 +0,0 @@ -# this needs to be run first -# in order to create the remote state for terraform -module "global_variables" { - source = "../modules/global_variables" -} - -provider "aws" { - region = module.global_variables.aws_region -} - -terraform { - required_version = ">= 1.4" - required_providers { - aws = { - source = "hashicorp/aws" - } - } -} - -resource "aws_s3_bucket" "terraform_state" { - bucket = "${module.global_variables.application}-terraform-state" - tags = { - Name = "S3 Remote Terraform State Store" - } -} - -resource "aws_s3_bucket_versioning" "tf_state_versioning" { - bucket = aws_s3_bucket.terraform_state.id - versioning_configuration { - status = "Enabled" - } -} - -resource "aws_dynamodb_table" "terraform_state" { - name = "${module.global_variables.application}-terraform-state" - read_capacity = 5 - write_capacity = 5 - hash_key = "LockID" - attribute { - name = "LockID" - type = "S" - } - tags = { - "Name" = "DynamoDB Terraform State Lock Table" - } -} diff --git a/{{cookiecutter.project_slug}}/terraform/github/oidc.tf b/{{cookiecutter.project_slug}}/terraform/github/oidc.tf deleted file mode 100644 index f67d7276..00000000 --- a/{{cookiecutter.project_slug}}/terraform/github/oidc.tf +++ /dev/null @@ -1,63 +0,0 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.51.1" - } - } - backend "s3" { - region = "{{ cookiecutter.aws_region }}" - bucket = "{{ cookiecutter.project_dash }}-terraform-state" - key = "{{ cookiecutter.project_dash }}.github.json" - encrypt = true - dynamodb_table = "{{ cookiecutter.project_dash }}-terraform-state" - } -} - -provider "aws" { - region = "us-east-1" -} - -resource "aws_iam_openid_connect_provider" "github" { - url = "https://token.actions.githubusercontent.com" - - client_id_list = [ - "sts.amazonaws.com" - ] - - # https://stackoverflow.com/questions/69247498/how-can-i-calculate-the-thumbprint-of-an-openid-connect-server - # Thumbprints for GitHub - thumbprint_list = [ - "6938fd4d98bab03faadb97b34396831e3780aea1", - "1c58a3a8518e8759bf075b76b750d4f2df264fcd" - ] -} - -# Define the IAM role -resource "aws_iam_role" "github_oidc_role" { - name = "{{ cookiecutter.project_slug }}-github-oidc-role" - - assume_role_policy = <<EOF -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Principal": { - "Federated": "${aws_iam_openid_connect_provider.github.arn}" - }, - "Action": "sts:AssumeRoleWithWebIdentity", - "Condition": { - "StringLike": { - "token.actions.githubusercontent.com:sub": "repo:{{ cookiecutter.source_control_organization_slug }}/{{ cookiecutter.repo_name }}:*" - }, - "StringEquals": { - "token.actions.githubusercontent.com:aud": "sts.amazonaws.com" - } - } - } - } - ] -} -EOF -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/Makefile b/{{cookiecutter.project_slug}}/terraform/modules/base/Makefile deleted file mode 100644 index babb6340..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/Makefile +++ /dev/null @@ -1,63 +0,0 @@ -.terraform.lock.hcl: - terraform init - -init: .terraform.lock.hcl - -plan: - @echo "=======================================================================" - @echo "IMPORTANT: Please make sure that you are on the VPN before you continue" - @echo "=======================================================================" - terraform plan -out="tfplan.out" - @terraform show -no-color tfplan.out >> .terraform/tfplan-$$(date +%Y%m%d-%H%M%S).log - -tfplan.out: plan - -apply: tfplan.out - # TODO: Add check to see if you are on the VPN - tofu apply "tfplan.out" - -kubeconfig: - tofu output -raw kubeconfig > ./kubeconfig - -remove-kube-state: - rm -f kubeconfig - tofu state rm helm_release.argocd \ - kubernetes_namespace.monitoring || true - -# TODO: add cookiecutter.use_talos check for talos targets -talosconfig: - tofu output -raw talosconfig > ./talosconfig - -remove-talos-state: - rm -f talosconfig - tofu state rm data.talos_client_configuration.this \ - data.talos_cluster_kubeconfig.this || true - -talos-health: - @echo "Fetching Talos node public IPs..." - @ips=$$(tofu output talos_node_public_ips | tr -d '"') ; \ - first_ip=$$(echo $$ips | cut -d',' -f1) ; \ - echo "Running health check on Talos node at IP: $$first_ip" ; \ - talosctl health --nodes $$first_ip - -talos-version: - @echo "Fetching Talos node public IPs..." - @ips=$$(tofu output talos_node_public_ips | tr -d '"') ; \ - IFS=',' read -r -a ip_array <<< "$$ips" ; \ - for ip in $${ip_array[@]} ; do \ - talosctl --nodes $$ip version --short ; \ - done - -upgrade-talos: - @echo "Fetching Talos node public IPs..." - @ips=$$(tofu output talos_node_public_ips | tr -d '"') ; \ - IFS=',' read -r -a ip_array <<< "$$ips" ; \ - for ip in $${ip_array[@]} ; do \ - echo "Upgrading Talos node at IP: $$ip" ; \ - talosctl upgrade --nodes $$ip \ - --image factory.talos.dev/installer/10e276a06c1f86b182757a962258ac00655d3425e5957f617bdc82f06894e39b:v1.7.4 ; \ - done - -destroy: remove-kube-state remove-talos-state - tofu destroy - diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/acm.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/acm.tf deleted file mode 100644 index 0be398c4..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/acm.tf +++ /dev/null @@ -1,22 +0,0 @@ -resource "aws_acm_certificate" "cert" { - domain_name = var.domain_name - validation_method = "DNS" - provider = aws.us_east_1 - - lifecycle { - create_before_destroy = true - } -} - -resource "aws_route53_record" "cert" { - name = tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_name - type = tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_type - zone_id = aws_route53_zone.route_zone.id - records = [tolist(aws_acm_certificate.cert.domain_validation_options)[0].resource_record_value] - ttl = 300 -} - -resource "aws_acm_certificate_validation" "cert" { - certificate_arn = aws_acm_certificate.cert.arn - validation_record_fqdns = aws_route53_record.cert.*.fqdn -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/backend.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/backend.tf deleted file mode 100644 index 4d73c43b..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/backend.tf +++ /dev/null @@ -1,9 +0,0 @@ -provider "aws" { - region = var.aws_region -} - -# us-east-1 is the only region that supports ACM certificates -provider "aws" { - region = "us-east-1" - alias = "us_east_1" -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/cloudfront.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/cloudfront.tf deleted file mode 100644 index 39fb0d92..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/cloudfront.tf +++ /dev/null @@ -1,110 +0,0 @@ -data "aws_cloudfront_cache_policy" "caching_optimized" { - name = "Managed-CachingOptimized" -} - -data "aws_cloudfront_cache_policy" "caching_disabled" { - name = "Managed-CachingDisabled" -} - -data "aws_cloudfront_origin_request_policy" "all_viewer_except_host" { - name = "Managed-AllViewerExceptHostHeader" -} - -resource "aws_cloudfront_origin_access_identity" "s3_access_identity" { - comment = "${var.app_name}-${var.environment}" -} - -resource "aws_cloudfront_origin_access_control" "static_storage" { - name = "${var.app_name}-${var.environment}-static-storage" - description = "Backend Bucket Access Policy" - origin_access_control_origin_type = "s3" - signing_behavior = "always" - signing_protocol = "sigv4" -} - -resource "aws_cloudfront_distribution" "cloudfront" { - enabled = true - aliases = [var.domain_name] - is_ipv6_enabled = true - price_class = "PriceClass_100" - default_root_object = "" - - // Django static storage s3 bucket - origin { - domain_name = aws_s3_bucket.static_storage.bucket_regional_domain_name - origin_id = aws_s3_bucket.static_storage.id - origin_access_control_id = aws_cloudfront_origin_access_control.static_storage.id - } - - - // Kubernetes cluster - origin { - domain_name = var.nextjs_domain_name - origin_id = var.cluster_name - - custom_origin_config { - http_port = 80 - https_port = 443 - origin_protocol_policy = "match-viewer" - origin_ssl_protocols = ["TLSv1.1", "TLSv1.2"] - } - } - - // Cache behavior for /api paths - ordered_cache_behavior { - path_pattern = "/api/*" - target_origin_id = var.cluster_name - allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] - cached_methods = ["GET", "HEAD"] - viewer_protocol_policy = "redirect-to-https" - cache_policy_id = data.aws_cloudfront_cache_policy.caching_disabled.id - origin_request_policy_id = data.aws_cloudfront_origin_request_policy.all_viewer_except_host.id - } - - default_cache_behavior { - cache_policy_id = data.aws_cloudfront_cache_policy.caching_disabled.id - origin_request_policy_id = data.aws_cloudfront_origin_request_policy.all_viewer_except_host.id - allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"] - cached_methods = ["GET", "HEAD"] - viewer_protocol_policy = "redirect-to-https" - target_origin_id = var.cluster_name - } - - viewer_certificate { - ssl_support_method = "sni-only" - acm_certificate_arn = aws_acm_certificate.cert.arn - minimum_protocol_version = "TLSv1.2_2018" - } - - restrictions { - geo_restriction { - restriction_type = "none" - } - } - - tags = local.common_tags -} - -resource "aws_iam_user" "cloudfront_invalidator" { - name = "${var.app_name}-${var.environment}-cloudfront-invalidator" -} - -resource "aws_iam_user_policy" "cloudfront_invalidator" { - name = "${var.app_name}-${var.environment}-cloudfront-invalidator" - user = aws_iam_user.cloudfront_invalidator.name - policy = data.aws_iam_policy_document.cloudfront_invalidator.json -} - -data "aws_iam_policy_document" "cloudfront_invalidator" { - statement { - sid = "CloudfrontInvalidation" - actions = ["cloudfront:CreateInvalidation"] - effect = "Allow" - resources = [aws_cloudfront_distribution.cloudfront.arn] - } -} - -resource "aws_iam_access_key" "cloudfront_invalidator" { - user = aws_iam_user.cloudfront_invalidator.name -} - diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/ec2-iam-role.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/ec2-iam-role.tf deleted file mode 100644 index dbdc08d7..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/ec2-iam-role.tf +++ /dev/null @@ -1,116 +0,0 @@ -# Create IAM policy for S3 access -resource "aws_iam_policy" "s3_rw_policy" { - name = "${var.app_name}-${var.environment}-S3ReadWritePolicy" - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Action = [ - "s3:PutObject", - "s3:GetObjectAcl", - "s3:GetObject", - "s3:ListBucket", - "s3:DeleteObject", - "s3:PutObjectAcl" - ] - Resource = [ - "${aws_s3_bucket.backups.arn}", - "${aws_s3_bucket.backups.arn}/*", - "${aws_s3_bucket.static_storage.arn}", - "${aws_s3_bucket.static_storage.arn}/*" - ] - } - ] - }) -} - -# Create AssumeRole IAM role for EC2 instances -resource "aws_iam_role" "ec2_role" { - name = "${var.app_name}-${var.environment}-EC2S3ReadWriteRole" - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Principal = { - Service = "ec2.amazonaws.com" - } - Action = "sts:AssumeRole" - } - ] - }) -} - -# Attach the S3 policy to the role -resource "aws_iam_role_policy_attachment" "attach_s3_rw_policy" { - role = aws_iam_role.ec2_role.name - policy_arn = aws_iam_policy.s3_rw_policy.arn -} - -# Create an instance profile for the role -resource "aws_iam_instance_profile" "ec2_instance_profile" { - name = "${var.app_name}-${var.environment}-EC2InstanceProfile" - role = aws_iam_role.ec2_role.name -} - -# Create ECR read policy for EC2 instances -resource "aws_iam_policy" "ecr_read_policy" { - name = "${var.app_name}-${var.environment}-ECRReadPolicy" - description = "Policy to allow read access to an ECR repository" - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Action = [ - "ecr:GetAuthorizationToken", - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:BatchCheckLayerAvailability", - "ecr:GetRepositoryPolicy", - "ecr:DescribeRepositories", - "ecr:ListImages", - "ecr:DescribeImages", - "ecr:DescribeImageScanFindings" - ] - Resource = "*" - } - ] - }) -} - -# Attach the ECR policy to the ec2 role -resource "aws_iam_role_policy_attachment" "ecr_read_policy_attachment" { - role = aws_iam_role.ec2_role.name - policy_arn = aws_iam_policy.ecr_read_policy.arn -} -{% if cookiecutter.mail_service == "Amazon SES" %} - -# Create Amazon SES policy for EC2 instances -resource "aws_iam_policy" "amazon_ses_policy" { - name = "${var.app_name}-${var.environment}-AmazonSES" - description = "Allow sending email using Amazon SES" - policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Effect = "Allow" - Action = [ - "ses:SendEmail", - "ses:SendRawEmail", - "ses:GetSendQuota", - "ses:GetSendStatistics" - ] - Resource = "*" - } - ] - }) -} - -# Attach the Amazon SES policy to the ec2 role -resource "aws_iam_role_policy_attachment" "amazon_ses_policy_attachment" { - role = aws_iam_role.ec2_role.name - policy_arn = aws_iam_policy.amazon_ses_policy.arn -} -{% endif %} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/ec2.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/ec2.tf deleted file mode 100644 index dc055656..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/ec2.tf +++ /dev/null @@ -1,61 +0,0 @@ -{% if cookiecutter.operating_system == "talos" %} -data "aws_ami" "os" { - owners = ["540036508848"] # Sidero Labs - most_recent = true - name_regex = "^talos-v\\d+\\.\\d+\\.\\d+-${data.aws_availability_zones.available.id}-amd64$" -} -{%- elif cookiecutter.operating_system == "k3s" %} -data "aws_ami" "os" { - most_recent = true - owners = ["099720109477"] # Canonical - filter { - name = "name" - values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] - } - - filter { - name = "virtualization-type" - values = ["hvm"] - } -} - -resource "tls_private_key" "deploy_key" { - algorithm = "ED25519" -} - -resource "aws_key_pair" "default_key" { - key_name = "hotelnames_deploy_key" - public_key = tls_private_key.deploy_key.public_key_openssh -} - -{%- endif %} - -locals { - cluster_required_tags = { - "kubernetes.io/cluster/${var.cluster_name}" = "owned" - } -} - -module "control_plane_nodes" { - source = "terraform-aws-modules/ec2-instance/aws" - version = "~> 5.6.1" - - count = var.control_plane.num_instances - - name = "${var.cluster_name}-${count.index}" - ami = var.control_plane.ami_id == null ? data.aws_ami.os.id : var.control_plane.ami_id - monitoring = true - instance_type = var.control_plane.instance_type - iam_instance_profile = aws_iam_instance_profile.ec2_instance_profile.name - subnet_id = element(module.vpc.public_subnets, count.index) - iam_role_use_name_prefix = false - create_iam_instance_profile = false - tags = merge(local.common_tags, local.cluster_required_tags) - -{%- if cookiecutter.operating_system == "k3s" %} - key_name = aws_key_pair.default_key.key_name -{%- endif %} - - vpc_security_group_ids = [module.cluster_sg.security_group_id] -} - diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/ecr.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/ecr.tf deleted file mode 100644 index 7069181e..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/ecr.tf +++ /dev/null @@ -1,57 +0,0 @@ -{% if cookiecutter.create_nextjs_frontend == "y" %} -module "ecr_frontend" { - source = "terraform-aws-modules/ecr/aws" - version = "1.6.0" - - repository_name = var.frontend_ecr_repo - repository_image_tag_mutability = "MUTABLE" - - repository_lifecycle_policy = jsonencode({ - rules = [ - { - rulePriority = 1, - description = "Keep last 5 images", - selection = { - tagStatus = "tagged", - tagPrefixList = ["v"], - countType = "imageCountMoreThan", - countNumber = 5 - }, - action = { - type = "expire" - } - } - ] - }) - - tags = local.common_tags -} -{% endif %} - -module "ecr_backend" { - source = "terraform-aws-modules/ecr/aws" - version = "1.6.0" - - repository_name = var.backend_ecr_repo - repository_image_tag_mutability = "MUTABLE" - - repository_lifecycle_policy = jsonencode({ - rules = [ - { - rulePriority = 1, - description = "Keep last 5 images", - selection = { - tagStatus = "tagged", - tagPrefixList = ["v"], - countType = "imageCountMoreThan", - countNumber = 5 - }, - action = { - type = "expire" - } - } - ] - }) - - tags = local.common_tags -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/elb.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/elb.tf deleted file mode 100644 index 7b92d1de..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/elb.tf +++ /dev/null @@ -1,44 +0,0 @@ -module "elb_k8s_elb" { - source = "terraform-aws-modules/elb/aws" - version = "~> 4.0" - - name = "${var.cluster_name}-k8s-api" - subnets = module.vpc.public_subnets - tags = merge(local.common_tags, local.cluster_required_tags) - - security_groups = [module.cluster_sg.security_group_id] - - listener = [ - { - lb_port = 80 - lb_protocol = "tcp" - instance_port = 30080 - instance_protocol = "tcp" - }, - { - lb_port = 443 - lb_protocol = "tcp" - instance_port = 30443 - instance_protocol = "tcp" - }, - { - lb_port = 6443 - lb_protocol = "tcp" - instance_port = 6443 - instance_protocol = "tcp" - }, - ] - - health_check = { - target = "tcp:6443" - interval = 30 - healthy_threshold = 2 - unhealthy_threshold = 2 - timeout = 5 - } - - number_of_instances = var.control_plane.num_instances - instances = module.control_plane_nodes.*.id -} - - diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/github-iam-role.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/github-iam-role.tf deleted file mode 100644 index c05d1431..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/github-iam-role.tf +++ /dev/null @@ -1,43 +0,0 @@ -data "aws_iam_role" "github_oidc_role" { - name = "{{ cookiecutter.project_slug }}-github-oidc-role" -} - -# Define the IAM policy for ECR -resource "aws_iam_policy" "ecr_push_policy" { - name = "${var.app_name}-${var.repo_name}-ecr-push-policy" - description = "Policy to allow pushing images to ECR" - - policy = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Effect = "Allow", - Action = [ - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:BatchCheckLayerAvailability", - "ecr:PutImage", - "ecr:InitiateLayerUpload", - "ecr:UploadLayerPart", - "ecr:CompleteLayerUpload" - ], - Resource = [ - {% if cookiecutter.create_nextjs_frontend == "y" %}"arn:aws:ecr:${var.aws_region}:${var.account_id}:repository/${var.frontend_ecr_repo}",{% endif %} - "arn:aws:ecr:${var.aws_region}:${var.account_id}:repository/${var.backend_ecr_repo}", - ] - }, - { - Effect = "Allow", - Action = "ecr:GetAuthorizationToken", - Resource = "*" - } - ] - }) -} - -# Attach the policy to the role -resource "aws_iam_role_policy_attachment" "ecr_push_policy_attachment" { - role = data.aws_iam_role.github_oidc_role.name - policy_arn = aws_iam_policy.ecr_push_policy.arn -} - diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/iam.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/iam.tf deleted file mode 100644 index 4d4985ae..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/iam.tf +++ /dev/null @@ -1,31 +0,0 @@ -resource "aws_iam_user" "cnpg_user" { - name = "${var.app_name}-${var.environment}-cnpg-user" - - tags = local.common_tags -} - -resource "aws_iam_access_key" "cnpg_user_key" { - user = aws_iam_user.cnpg_user.name -} - -resource "aws_iam_user_policy_attachment" "cnpg_user_policy_attachment" { - user = aws_iam_user.cnpg_user.name - policy_arn = aws_iam_policy.s3_rw_policy.arn -} -{% if cookiecutter.mail_service == "Amazon SES" %} - -resource "aws_iam_user" "amazon_ses_user" { - name = "${var.app_name}-${var.environment}-ses-user" - - tags = local.common_tags -} - -resource "aws_iam_access_key" "amazon_ses_user_key" { - user = aws_iam_user.amazon_ses_user.name -} - -resource "aws_iam_user_policy_attachment" "amazon_ses_user_policy_attachment" { - user = aws_iam_user.amazon_ses_user.name - policy_arn = aws_iam_policy.amazon_ses_policy.arn -} -{% endif %} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/locals.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/locals.tf deleted file mode 100644 index 398ab29a..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/locals.tf +++ /dev/null @@ -1,8 +0,0 @@ -locals { - common_tags = merge(var.tags, { - automation = "terraform" - "automation.config" = join(".", [var.app_name, var.environment]) - application = var.app_name - environment = var.environment - }) -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/outputs.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/outputs.tf deleted file mode 100644 index ce305c19..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/outputs.tf +++ /dev/null @@ -1,44 +0,0 @@ -output "cnpg-iam-role-arn" { - description = "CloudNativePG iam role arn" - value = aws_iam_role.ec2_role.arn - sensitive = false -} - -output "cnpg_user_access_key" { - value = aws_iam_access_key.cnpg_user_key.id -} - -output "cnpg_user_secret_key" { - sensitive = true - value = aws_iam_access_key.cnpg_user_key.secret -} -{% if cookiecutter.mail_service == "Amazon SES" %} - -output "amazon_ses_user_key" { - value = aws_iam_access_key.amazon_ses_user_key.id -} - -output "amazon_ses_user_secret_key" { - sensitive = true - value = aws_iam_access_key.amazon_ses_user_key.secret -} -{% endif %} - -output "control_plane_nodes_public_ips" { - description = "The public ip addresses of the control plane nodes." - value = join(",", module.control_plane_nodes.*.public_ip) -} - -output "control_plane_nodes_private_ips" { - description = "The private ip addresses of the control plane nodes." - value = join(",", module.control_plane_nodes.*.private_ip) -} - -output "private_deploy_key" { - value = tls_private_key.deploy_key.private_key_openssh - sensitive = true -} - -output "public_deploy_key" { - value = tls_private_key.deploy_key.public_key_openssh -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/route53.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/route53.tf deleted file mode 100644 index 64643fbd..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/route53.tf +++ /dev/null @@ -1,70 +0,0 @@ -resource "aws_route53_zone" "route_zone" { - name = var.domain_name - tags = local.common_tags -} - -resource "aws_route53_record" "api" { - zone_id = aws_route53_zone.route_zone.zone_id - name = var.api_domain_name - type = "CNAME" - records = [module.elb_k8s_elb.elb_dns_name] - ttl = 600 -} - -resource "aws_route53_record" "k8s" { - zone_id = aws_route53_zone.route_zone.zone_id - name = var.cluster_domain_name - type = "CNAME" - records = [module.elb_k8s_elb.elb_dns_name] - ttl = 600 -} - -resource "aws_route53_record" "nextjs" { - zone_id = aws_route53_zone.route_zone.zone_id - name = var.nextjs_domain_name - type = "CNAME" - records = [module.elb_k8s_elb.elb_dns_name] - ttl = 600 -} - -resource "aws_route53_record" "frontend" { - zone_id = aws_route53_zone.route_zone.zone_id - name = var.domain_name - type = "A" - - alias { - name = aws_cloudfront_distribution.cloudfront.domain_name - zone_id = aws_cloudfront_distribution.cloudfront.hosted_zone_id - evaluate_target_health = false - } -} - -resource "aws_route53_record" "frontend-v6" { - zone_id = aws_route53_zone.route_zone.zone_id - name = var.domain_name - type = "AAAA" - - alias { - name = aws_cloudfront_distribution.cloudfront.domain_name - zone_id = aws_cloudfront_distribution.cloudfront.hosted_zone_id - evaluate_target_health = false - } -} - -# record for argocd call -resource "aws_route53_record" "argocd" { - zone_id = aws_route53_zone.route_zone.zone_id - name = var.argocd_domain_name - type = "CNAME" - records = [module.elb_k8s_elb.elb_dns_name] - ttl = 600 -} - -# record for prometheus call -resource "aws_route53_record" "prometheus" { - zone_id = aws_route53_zone.route_zone.zone_id - name = var.prometheus_domain_name - type = "CNAME" - records = [module.elb_k8s_elb.elb_dns_name] - ttl = 600 -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/s3.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/s3.tf deleted file mode 100644 index 66897d81..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/s3.tf +++ /dev/null @@ -1,88 +0,0 @@ -resource "aws_s3_bucket" "backups" { - bucket = "${var.app_name}-${var.environment}-backups" - tags = local.common_tags -} - -resource "aws_s3_bucket_server_side_encryption_configuration" "backups" { - bucket = aws_s3_bucket.backups.bucket - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "AES256" - } - } -} - -resource "aws_s3_bucket" "static_storage" { - bucket = "${var.app_name}-${var.environment}-static-storage" - tags = local.common_tags -} - -resource "aws_s3_bucket_server_side_encryption_configuration" "static_storage" { - bucket = aws_s3_bucket.static_storage.bucket - - rule { - apply_server_side_encryption_by_default { - sse_algorithm = "AES256" - } - } -} - -resource "aws_s3_bucket_cors_configuration" "static_storage" { - bucket = aws_s3_bucket.static_storage.id - - cors_rule { - allowed_headers = ["Authorization", "Content-Length"] - allowed_methods = [ - "GET", - "PUT", - "POST", - "DELETE", - "HEAD" - ] - allowed_origins = ["*"] - } -} - -resource "aws_s3_bucket_versioning" "static_storage" { - bucket = aws_s3_bucket.static_storage.id - versioning_configuration { - status = "Enabled" - } -} - -resource "aws_s3_bucket_ownership_controls" "static_storage" { - bucket = aws_s3_bucket.static_storage.id - rule { - object_ownership = "ObjectWriter" - } -} - -resource "aws_s3_bucket_acl" "static_storage" { - depends_on = [aws_s3_bucket_ownership_controls.static_storage] - - bucket = aws_s3_bucket.static_storage.id - acl = "private" -} - -resource "aws_s3_bucket_policy" "static_storage" { - bucket = aws_s3_bucket.static_storage.id - policy = <<EOF -{ - "Version": "2012-10-17", - "Statement": { - "Sid": "AllowCloudFrontServicePrincipalReadOnly", - "Effect": "Allow", - "Principal": { - "Service": "cloudfront.amazonaws.com" - }, - "Action": "s3:GetObject", - "Resource": "${aws_s3_bucket.static_storage.arn}/*", - "Condition": { - "StringEquals": { - "AWS:SourceArn": "${aws_cloudfront_distribution.cloudfront.arn}" - } - } - } -} -EOF -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/security_groups.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/security_groups.tf deleted file mode 100644 index f0df4dc7..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/security_groups.tf +++ /dev/null @@ -1,61 +0,0 @@ -module "cluster_sg" { - source = "terraform-aws-modules/security-group/aws" - version = "~> 4.0" - - name = var.cluster_name - description = "Allow all intra-cluster and egress traffic" - vpc_id = module.vpc.vpc_id - tags = local.common_tags - - ingress_with_self = [ - { - rule = "all-all" - }, - ] - - ingress_with_cidr_blocks = [ - { - from_port = 80 - to_port = 80 - protocol = "tcp" - cidr_blocks = "0.0.0.0/0" - }, - { - from_port = 443 - to_port = 443 - protocol = "tcp" - cidr_blocks = "0.0.0.0/0" - }, - { - from_port = 6443 - to_port = 6443 - protocol = "tcp" - cidr_blocks = var.admin_allowed_ips - description = "Kubernetes API Access" - }, -{% if cookiecutter.operating_system == "talos" %} - { - from_port = 50000 - to_port = 50000 - protocol = "tcp" - cidr_blocks = var.admin_allowed_ips - description = "Talos API Access" - }, -{%- elif cookiecutter.operating_system == "k3s" %} - { - from_port = 22 - to_port = 22 - protocol = "tcp" - cidr_blocks = var.admin_allowed_ips - description = "Talos API Access" - }, -{%- endif %} - ] - - egress_with_cidr_blocks = [ - { - rule = "all-all" - cidr_blocks = "0.0.0.0/0" - }, - ] -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/variables.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/variables.tf deleted file mode 100644 index 376a043f..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/variables.tf +++ /dev/null @@ -1,134 +0,0 @@ -variable "account_id" { - description = "The AWS account ID" - type = string - default = "{{ cookiecutter.aws_account_id }}" -} - -variable "aws_region" { - type = string - description = "AWS Region" - default = "{{ cookiecutter.aws_region }}" -} - -variable "app_name" { - description = "Application Name" - type = string - default = "{{ cookiecutter.project_dash }}" -} - -variable "environment" { - description = "Environment Name" - type = string - default = "sandbox" -} - -variable "cluster_name" { - description = "Name of cluster" - type = string - default = "{{ cookiecutter.project_dash }}-sandbox" -} - -variable "domain_name" { - type = string - default = "{{ cookiecutter.domain_name }}" -} - -variable "api_domain_name" { - type = string - default = "api.{{ cookiecutter.domain_name }}" -} - -variable "cluster_domain_name" { - type = string - default = "k8s.{{ cookiecutter.domain_name }}" -} - -variable "nextjs_domain_name" { - type = string - default = "nextjs.{{ cookiecutter.domain_name }}" -} - -variable "argocd_domain_name" { - type = string - default = "argocd.{{ cookiecutter.domain_name }}" -} - - -variable "prometheus_domain_name" { - type = string - default = "prometheus.{{ cookiecutter.domain_name }}" -} - -variable "kubernetes_version" { - - description = "Kubernetes version to use for the cluster, if not set the k8s version shipped with the talos sdk or k3s version will be used" - type = string - default = null -} - -variable "control_plane" { - description = "Info for control plane that will be created" - type = object({ - instance_type = optional(string, "t3a.medium") - ami_id = optional(string, null) - num_instances = optional(number, 3) - config_patch_files = optional(list(string), []) - tags = optional(map(string), {}) - }) - - validation { - condition = var.control_plane.ami_id != null ? (length(var.control_plane.ami_id) > 4 && substr(var.control_plane.ami_id, 0, 4) == "ami-") : true - error_message = "The ami_id value must be a valid AMI id, starting with \"ami-\"." - } - - default = {} -} - -variable "cluster_vpc_cidr" { - description = "The IPv4 CIDR block for the VPC." - type = string - default = "172.16.0.0/16" -} - -{% if cookiecutter.operating_system == "talos" %} -variable "config_patch_files" { - description = "Path to talos config path files that applies to all nodes" - type = list(string) - default = [] -} -{%- endif %} - -variable "repo_name" { - type = string - default = "{{ cookiecutter.repo_name }}" -} - -variable "repo_url" { - type = string - default = "{{ cookiecutter.repo_url }}" -} - -{% if cookiecutter.create_nextjs_frontend == "y" %} -variable "frontend_ecr_repo" { - description = "The Frontend ECR repository name" - type = string - default = "{{ cookiecutter.project_dash }}-sandbox-frontend" -} -{% endif %} - -variable "backend_ecr_repo" { - description = "The backend ECR repository name" - type = string - default = "{{ cookiecutter.project_dash }}-sandbox-backend" -} - -variable "admin_allowed_ips" { - description = "A list of CIDR blocks that are allowed to access the kubernetes api" - type = string - default = "0.0.0.0/0" -} - -variable "tags" { - type = map(string) - default = {} -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/versions.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/versions.tf deleted file mode 100644 index 932fa456..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/versions.tf +++ /dev/null @@ -1,21 +0,0 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = "5.51" - } - # TODO: add cookiecutter.use_talos check - talos = { - source = "siderolabs/talos" - version = "0.5.0" - } - null = { - source = "hashicorp/null" - version = "3.2.2" - } - local = { - source = "hashicorp/local" - version = ">= 2.5.1" - } - } -} diff --git a/{{cookiecutter.project_slug}}/terraform/modules/base/vpc.tf b/{{cookiecutter.project_slug}}/terraform/modules/base/vpc.tf deleted file mode 100644 index dd3e59d1..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/base/vpc.tf +++ /dev/null @@ -1,22 +0,0 @@ -data "aws_availability_zones" "available" { - state = "available" -} - -module "vpc" { - source = "terraform-aws-modules/vpc/aws" - version = "~> 5.1" - - name = var.cluster_name - cidr = var.cluster_vpc_cidr - tags = local.common_tags - - enable_nat_gateway = false - - map_public_ip_on_launch = true - - # lets pick utmost three AZ's since the CIDR bit is 2 - azs = slice(data.aws_availability_zones.available.names, 0, 3) - public_subnets = [for i, v in slice(data.aws_availability_zones.available.names, 0, 3) : cidrsubnet(var.cluster_vpc_cidr, 2, i)] -} - - diff --git a/{{cookiecutter.project_slug}}/terraform/modules/global_variables/main.tf b/{{cookiecutter.project_slug}}/terraform/modules/global_variables/main.tf deleted file mode 100644 index 9b02036c..00000000 --- a/{{cookiecutter.project_slug}}/terraform/modules/global_variables/main.tf +++ /dev/null @@ -1,26 +0,0 @@ -output "app_name" { - description = "App Name" - value = "{{ cookiecutter.project_dash }}" -} - -output "application" { - value = "{{ cookiecutter.project_dash }}" -} - -output "aws_region" { - description = "AWS Region" - value = "{{ cookiecutter.aws_region }}" -} - -output "aws_profile" { - description = "AWS Profile for CLI" - value = "{{ cookiecutter.project_dash }}" -} - -output "account_id" { - value = "{{ cookiecutter.aws_account_id }}" -} - -output "domain_name" { - value = "{{ cookiecutter.domain_name }}" -} diff --git a/{{cookiecutter.project_slug}}/terraform/prod/backend.tf b/{{cookiecutter.project_slug}}/terraform/prod/backend.tf deleted file mode 100644 index 09cd0a2f..00000000 --- a/{{cookiecutter.project_slug}}/terraform/prod/backend.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_version = ">= 1.4" - backend "s3" { - region = "{{ cookiecutter.aws_region }}" - bucket = "{{ cookiecutter.project_dash }}-terraform-state" - key = "{{ cookiecutter.project_slug }}.prod.json" - encrypt = true - dynamodb_table = "{{ cookiecutter.project_dash }}-terraform-state" - } -} diff --git a/{{cookiecutter.project_slug}}/terraform/prod/cluster.tf b/{{cookiecutter.project_slug}}/terraform/prod/cluster.tf deleted file mode 100644 index 7a3eb0bb..00000000 --- a/{{cookiecutter.project_slug}}/terraform/prod/cluster.tf +++ /dev/null @@ -1,22 +0,0 @@ -module "cluster" { - source = "../modules/base" - environment = "prod" - cluster_name = "{{ cookiecutter.project_dash }}-prod" - domain_name = "prod.{{ cookiecutter.domain_name }}" - api_domain_name = "api.prod.{{ cookiecutter.domain_name }}" - cluster_domain_name = "k8s.prod.{{ cookiecutter.domain_name }}" - argocd_domain_name = "argocd.prod.{{ cookiecutter.domain_name }}" - prometheus_domain_name = "prometheus.prod.{{ cookiecutter.domain_name }}" - control_plane = { - # 2 vCPUs, 4 GiB RAM, $0.0376 per Hour - instance_type = "t3a.medium" - num_instances = 3 - # NB!: set ami_id to prevent instance recreation when the latest ami - # changes, eg: - # ami_id = "ami-09d22b42af049d453" - } - - # NB!: limit admin_allowed_ips to a set of trusted - # public ip addresses. Both variables are comma separated lists of ips. - # admin_allowed_ips = "10.0.0.1/32,10.0.0.2/32" -} diff --git a/{{cookiecutter.project_slug}}/terraform/prod/outputs.tf b/{{cookiecutter.project_slug}}/terraform/prod/outputs.tf deleted file mode 100644 index c1aedf13..00000000 --- a/{{cookiecutter.project_slug}}/terraform/prod/outputs.tf +++ /dev/null @@ -1,30 +0,0 @@ -output "cnpg-iam-role-arn" { - description = "CloudNativePG iam role arn" - value = module.cluster.cnpg-iam-role-arn - sensitive = false -} - -output "cnpg_user_access_key" { - value = module.cluster.cnpg_user_access_key -} - -output "cnpg_user_secret_key" { - sensitive = true - value = module.cluster.cnpg_user_secret_key -} -{% if cookiecutter.mail_service == "Amazon SES" %} - -output "amazon_ses_user_key" { - value = module.cluster.amazon_ses_user_key -} - -output "amazon_ses_user_secret_key" { - sensitive = true - value = module.cluster.amazon_ses_user_key -} -{% endif %} - -output "control_plane_nodes_public_ips" { - description = "The public ip addresses of the talos control plane nodes" - value = module.cluster.control_plane_nodes_public_ips -} diff --git a/{{cookiecutter.project_slug}}/terraform/sandbox/backend.tf b/{{cookiecutter.project_slug}}/terraform/sandbox/backend.tf deleted file mode 100644 index 20477331..00000000 --- a/{{cookiecutter.project_slug}}/terraform/sandbox/backend.tf +++ /dev/null @@ -1,14 +0,0 @@ -terraform { - required_version = ">= 1.4" - backend "s3" { - region = "{{ cookiecutter.aws_region }}" - bucket = "{{ cookiecutter.project_dash }}-terraform-state" - key = "{{ cookiecutter.project_slug }}.sandbox.json" - encrypt = true - dynamodb_table = "{{ cookiecutter.project_dash }}-terraform-state" - } -} - -module "global_variables" { - source = "../modules/global_variables" -} diff --git a/{{cookiecutter.project_slug}}/terraform/sandbox/cluster.tf b/{{cookiecutter.project_slug}}/terraform/sandbox/cluster.tf deleted file mode 100644 index d1409e5b..00000000 --- a/{{cookiecutter.project_slug}}/terraform/sandbox/cluster.tf +++ /dev/null @@ -1,23 +0,0 @@ -module "cluster" { - source = "../modules/base" - environment = "sandbox" - cluster_name = "{{ cookiecutter.project_dash }}-sandbox" - domain_name = "sandbox.{{ cookiecutter.domain_name }}" - api_domain_name = "api.sandbox.{{ cookiecutter.domain_name }}" - cluster_domain_name = "k8s.sandbox.{{ cookiecutter.domain_name }}" - argocd_domain_name = "argocd.sandbox.{{ cookiecutter.domain_name }}" - prometheus_domain_name = "prometheus.sandbox.{{ cookiecutter.domain_name }}" - control_plane = { - # 2 vCPUs, 4 GiB RAM, $0.0376 per Hour - instance_type = "t3a.medium" - num_instances = 3 - # NB!: set ami_id to prevent instance recreation when the latest ami - # changes, eg: - # ami_id = "ami-09d22b42af049d453" - - } - - # NB!: limit admin_allowed_ips to a set of trusted - # public ip addresses. Both variables are comma separated lists of ips. - # admin_allowed_ips = "10.0.0.1/32,10.0.0.2/32" -} diff --git a/{{cookiecutter.project_slug}}/terraform/sandbox/outputs.tf b/{{cookiecutter.project_slug}}/terraform/sandbox/outputs.tf deleted file mode 100644 index 24f3a214..00000000 --- a/{{cookiecutter.project_slug}}/terraform/sandbox/outputs.tf +++ /dev/null @@ -1,30 +0,0 @@ -output "cnpg-iam-role-arn" { - description = "CloudNativePG iam role arn" - value = module.cluster.cnpg-iam-role-arn - sensitive = false -} - -output "cnpg_user_access_key" { - value = module.cluster.cnpg_user_access_key -} - -output "cnpg_user_secret_key" { - sensitive = true - value = module.cluster.cnpg_user_secret_key -} -{% if cookiecutter.mail_service == "Amazon SES" %} - -output "amazon_ses_user_key" { - value = module.cluster.amazon_ses_user_key -} - -output "amazon_ses_user_secret_key" { - sensitive = true - value = module.cluster.amazon_ses_user_secret_key -} -{% endif %} - -output "control_plane_nodes_public_ips" { - description = "The public ip addresses of the talos control plane nodes" - value = module.cluster.control_plane_nodes_public_ips -} diff --git a/{{cookiecutter.project_slug}}/terraform/staging/backend.tf b/{{cookiecutter.project_slug}}/terraform/staging/backend.tf deleted file mode 100644 index 3f898c2c..00000000 --- a/{{cookiecutter.project_slug}}/terraform/staging/backend.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_version = ">= 1.4" - backend "s3" { - region = "{{ cookiecutter.aws_region }}" - bucket = "{{ cookiecutter.project_dash }}-terraform-state" - key = "{{ cookiecutter.project_dash }}.staging.json" - encrypt = true - dynamodb_table = "{{ cookiecutter.project_dash }}-terraform-state" - } -} diff --git a/{{cookiecutter.project_slug}}/terraform/staging/cluster.tf b/{{cookiecutter.project_slug}}/terraform/staging/cluster.tf deleted file mode 100644 index 30c18195..00000000 --- a/{{cookiecutter.project_slug}}/terraform/staging/cluster.tf +++ /dev/null @@ -1,22 +0,0 @@ -module "cluster" { - source = "../modules/base" - environment = "staging" - cluster_name = "{{ cookiecutter.project_dash }}-staging" - domain_name = "staging.{{ cookiecutter.domain_name }}" - api_domain_name = "api.staging.{{ cookiecutter.domain_name }}" - cluster_domain_name = "k8s.staging.{{ cookiecutter.domain_name }}" - argocd_domain_name = "argocd.staging.{{ cookiecutter.domain_name }}" - prometheus_domain_name = "prometheus.staging.{{ cookiecutter.domain_name }}" - control_plane = { - # 2 vCPUs, 4 GiB RAM, $0.0376 per Hour - instance_type = "t3a.medium" - num_instances = 3 - # NB!: set ami_id to prevent instance recreation when the latest ami - # changes, eg: - # ami_id = "ami-09d22b42af049d453" - } - - # NB!: limit admin_allowed_ips to a set of trusted - # public ip addresses. Both variables are comma separated lists of ips. - # admin_allowed_ips = "10.0.0.1/32,10.0.0.2/32" -} diff --git a/{{cookiecutter.project_slug}}/terraform/staging/outputs.tf b/{{cookiecutter.project_slug}}/terraform/staging/outputs.tf deleted file mode 100644 index 7d16be24..00000000 --- a/{{cookiecutter.project_slug}}/terraform/staging/outputs.tf +++ /dev/null @@ -1,48 +0,0 @@ -output "talosconfig" { - description = "The generated talosconfig" - value = module.cluster.talosconfig - sensitive = true -} - -output "kubeconfig" { - description = "The generated kubeconfig" - value = module.cluster.kubeconfig - sensitive = true -} - -output "machineconfig" { - description = "The generated machineconfig" - value = module.cluster.machineconfig - sensitive = true -} - -output "cnpg-iam-role-arn" { - description = "CloudNativePG iam role arn" - value = module.cluster.cnpg-iam-role-arn - sensitive = false -} - -output "cnpg_user_access_key" { - value = module.cluster.cnpg_user_access_key -} - -output "cnpg_user_secret_key" { - sensitive = true - value = module.cluster.cnpg_user_secret_key -} -{% if cookiecutter.mail_service == "Amazon SES" %} - -output "amazon_ses_user_key" { - value = module.cluster.amazon_ses_user_key -} - -output "amazon_ses_user_secret_key" { - sensitive = true - value = module.cluster.amazon_ses_user_key -} -{% endif %} - -output "control_plane_nodes_public_ips" { - description = "The public ip addresses of the talos control plane nodes" - value = module.cluster.control_plane_nodes_public_ips -}