├── README.md ├── golang ├── .idea │ ├── .gitignore │ ├── email.iml │ └── modules.xml ├── Dockerfile ├── Dockerfile.prod ├── docker-compose.yaml ├── email │ └── email.go ├── go.mod ├── go.sum ├── kafka │ └── consumer.go └── main.go ├── img ├── golang.svg ├── nestjs.svg └── nextjs.png ├── k8s ├── golang │ ├── deployment.yaml │ └── secret.yaml ├── nestjs │ ├── deployment.yaml │ ├── secret.yaml │ └── service.yaml └── nextjs │ ├── deployment.yaml │ ├── secret.yaml │ └── service.yaml ├── kafka ├── README.md ├── connectors │ ├── sink-mongo-twitter.properties │ └── source-twitter.properties └── docker-compose.yaml ├── nestjs ├── .docker │ └── entrypoint.sh ├── .dockerignore ├── .env.example ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── .vscode │ └── settings.json ├── Dockerfile ├── Dockerfile.prod ├── README.md ├── api.http ├── docker-compose.yaml ├── nest-cli.json ├── package-lock.json ├── package.json ├── src │ ├── app.controller.spec.ts │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ ├── mail-list │ │ ├── dto │ │ │ ├── create-mail-list.dto.ts │ │ │ └── update-mail-list.dto.ts │ │ ├── mail-list.controller.spec.ts │ │ ├── mail-list.controller.ts │ │ ├── mail-list.module.ts │ │ ├── mail-list.service.spec.ts │ │ ├── mail-list.service.ts │ │ ├── schemas │ │ │ └── mail-list.schema.ts │ │ └── send-mail-tweets.job.ts │ ├── main.ts │ └── tweets │ │ ├── check-new-tweets │ │ ├── check-new-tweets.task.spec.ts │ │ └── check-new-tweets.task.ts │ │ ├── dto │ │ ├── create-tweet.dto.ts │ │ └── update-tweet.dto.ts │ │ ├── schemas │ │ └── tweet.schema.ts │ │ ├── tweets.controller.spec.ts │ │ ├── tweets.controller.ts │ │ ├── tweets.module.ts │ │ ├── tweets.service.spec.ts │ │ └── tweets.service.ts ├── test │ ├── app.e2e-spec.ts │ └── jest-e2e.json ├── tsconfig.build.json └── tsconfig.json └── nextjs ├── .docker └── entrypoint.sh ├── .dockerignore ├── .env.example ├── .eslintrc.json ├── .gitignore ├── .vscode └── settings.json ├── Dockerfile ├── Dockerfile.prod ├── README.md ├── docker-compose.yaml ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── postcss.config.js ├── public ├── favicon.ico └── vercel.svg ├── src ├── components │ ├── Button.tsx │ ├── Navbar.tsx │ ├── Title.tsx │ └── Tweet.tsx ├── pages │ ├── _app.tsx │ ├── api │ │ └── hello.ts │ ├── emails.tsx │ ├── index.tsx │ ├── pagina1.tsx │ └── tweets.tsx ├── styles │ ├── Home.module.css │ └── globals.css └── utils │ ├── http.ts │ ├── models.ts │ └── theme.ts ├── tailwind.config.js ├── tsconfig.json └── utility-first.html /README.md: -------------------------------------------------------------------------------- 1 | # Imersão Fullcycle 6 - Monitoramento de tweets 2 |  3 | 4 | Participe gratuitamente: https://imersao.fullcycle.com.br/ 5 | 6 | ## Sobre o repositório 7 | Esse repositório contém todo código utilizado durante as aulas para referência. 8 | 9 | Faça seu fork e também nos dê uma estrelinha para nos ajudar a divulgar o projeto. 10 | 11 | As instruções de instalações estão no README.md de cada projeto. 12 | 13 | ## Ordem recomendada de execução 14 | 15 | * Nest.js 16 | -------------------------------------------------------------------------------- /golang/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /golang/.idea/email.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /golang/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /golang/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.17 2 | 3 | WORKDIR /go/src 4 | 5 | RUN apt-get update && apt-get install build-essential librdkafka-dev -y 6 | 7 | CMD ["tail", "-f", "/dev/null"] -------------------------------------------------------------------------------- /golang/Dockerfile.prod: -------------------------------------------------------------------------------- 1 | FROM golang:1.17 2 | 3 | WORKDIR /go/src 4 | COPY . . 5 | RUN apt-get update && apt-get install build-essential librdkafka-dev -y 6 | RUN go build -o /go/bin/emails main.go 7 | 8 | CMD ["/go/bin/emails"] -------------------------------------------------------------------------------- /golang/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | app: 4 | build: . 5 | environment: 6 | - MAIL_HOST=smtp.sendgrid.net 7 | - MAIL_PORT=465 8 | - MAIL_USER=apikey 9 | - MAIL_PASSWORD=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 10 | - MAIL_FROM=argentinaluiz@gmail.com 11 | - BOOTSTRAP_SERVERS=pkc-ymrq7.us-east-2.aws.confluent.cloud:9092 12 | - SECURITY_PROTOCOL=SASL_SSL 13 | - SASL_MECHANISMS=PLAIN 14 | - SASL_USERNAME=XMNIRNUJXI3E7GCC 15 | - SASL_PASSWORD=CdaTkW32rtDoutQCcCrXHdlonmHjdGc71My3iwoYUxOLHqsnO2Rn5XKaS+FdmEuZ 16 | volumes: 17 | - .:/go/src/ 18 | extra_hosts: 19 | - "host.docker.internal:172.17.0.1" -------------------------------------------------------------------------------- /golang/email/email.go: -------------------------------------------------------------------------------- 1 | package email 2 | 3 | import ( 4 | "fmt" 5 | gomail "gopkg.in/mail.v2" 6 | ) 7 | 8 | type Email struct { 9 | Emails []string `json:"emails"` 10 | Subject string `json:"subject"` 11 | Body string `json:"body"` 12 | } 13 | 14 | func NewEmail() *Email { 15 | return &Email{} 16 | } 17 | 18 | type MailSender struct { 19 | From string 20 | Dialer *gomail.Dialer 21 | } 22 | 23 | func NewMailSender() *MailSender { 24 | return &MailSender{} 25 | } 26 | 27 | func (ms *MailSender) Send(emailChan chan Email, workerId int) error { 28 | m := gomail.NewMessage() 29 | m.SetHeader("From", ms.From) 30 | for ec := range emailChan { 31 | m.SetHeader("Subject", ec.Subject) 32 | m.SetBody("text/html", ec.Body) 33 | for _, to := range ec.Emails { 34 | m.SetHeader("To", to) 35 | fmt.Println("to: ", to, "workerId: ", workerId) 36 | if err := ms.Dialer.DialAndSend(m); err != nil { 37 | fmt.Println(err) 38 | panic(err) 39 | } 40 | } 41 | } 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /golang/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/codeedu/imersao6-email 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/confluentinc/confluent-kafka-go v1.8.2 7 | gopkg.in/mail.v2 v2.3.1 8 | ) 9 | 10 | require gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect 11 | -------------------------------------------------------------------------------- /golang/go.sum: -------------------------------------------------------------------------------- 1 | github.com/confluentinc/confluent-kafka-go v1.8.2 h1:PBdbvYpyOdFLehj8j+9ba7FL4c4Moxn79gy9cYKxG5E= 2 | github.com/confluentinc/confluent-kafka-go v1.8.2/go.mod h1:u2zNLny2xq+5rWeTQjFHbDzzNuba4P1vo31r9r4uAdg= 3 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= 4 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= 5 | gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= 6 | gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= 7 | -------------------------------------------------------------------------------- /golang/kafka/consumer.go: -------------------------------------------------------------------------------- 1 | package kafka 2 | 3 | import ckafka "github.com/confluentinc/confluent-kafka-go/kafka" 4 | 5 | type Consumer struct { 6 | ConfigMap *ckafka.ConfigMap 7 | Topics []string 8 | } 9 | 10 | func NewConsumer(configMap *ckafka.ConfigMap, topics []string) *Consumer { 11 | return &Consumer{ 12 | ConfigMap: configMap, 13 | Topics: topics, 14 | } 15 | } 16 | 17 | func (c *Consumer) Consume(msgChan chan *ckafka.Message) error { 18 | consumer, err := ckafka.NewConsumer(c.ConfigMap) 19 | if err != nil { 20 | panic(err) 21 | } 22 | err = consumer.SubscribeTopics(c.Topics, nil) 23 | if err != nil { 24 | panic(err) 25 | } 26 | for { 27 | msg, err := consumer.ReadMessage(-1) 28 | if err == nil { 29 | msgChan <- msg 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /golang/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "encoding/json" 6 | "fmt" 7 | "github.com/codeedu/imersao6-email/email" 8 | "github.com/codeedu/imersao6-email/kafka" 9 | ckafka "github.com/confluentinc/confluent-kafka-go/kafka" 10 | gomail "gopkg.in/mail.v2" 11 | "os" 12 | "strconv" 13 | ) 14 | 15 | func main() { 16 | var emailCh = make(chan email.Email) 17 | var msgChan = make(chan *ckafka.Message) 18 | 19 | port, _ := strconv.Atoi(os.Getenv("MAIL_PORT")) 20 | 21 | d := gomail.NewDialer( 22 | os.Getenv("MAIL_HOST"), 23 | port, 24 | os.Getenv("MAIL_USER"), 25 | os.Getenv("MAIL_PASSWORD"), 26 | ) 27 | d.TLSConfig = &tls.Config{InsecureSkipVerify: true} 28 | 29 | es := email.NewMailSender() 30 | es.From = os.Getenv("MAIL_FROM") 31 | es.Dialer = d 32 | 33 | for i := 1; i <= 2; i++ { 34 | go es.Send(emailCh, i) 35 | } 36 | 37 | configMapConsumer := &ckafka.ConfigMap{ 38 | //"bootstrap.servers": "kafka:9094", 39 | "bootstrap.servers": os.Getenv("BOOTSTRAP_SERVERS"), 40 | "security.protocol": os.Getenv("SECURITY_PROTOCOL"), 41 | "sasl.mechanisms": os.Getenv("SASL_MECHANISMS"), 42 | "sasl.username": os.Getenv("SASL_USERNAME"), 43 | "sasl.password": os.Getenv("SASL_PASSWORD"), 44 | "client.id": "goapp", 45 | "group.id": "goapp1", 46 | "session.timeout.ms": 45000, 47 | } 48 | topics := []string{"emails"} 49 | consumer := kafka.NewConsumer(configMapConsumer, topics) 50 | go consumer.Consume(msgChan) 51 | 52 | fmt.Println("Consumindo msgs") 53 | for msg := range msgChan { 54 | var input email.Email 55 | json.Unmarshal(msg.Value, &input) 56 | emailCh <- input 57 | } 58 | } 59 | 60 | // { "emails": [ "wesley@fullcycle.com.br" ], "subject": "Novos tweets encontrados", "body": "Acesse o link Clique aqui" } 61 | -------------------------------------------------------------------------------- /img/golang.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/nestjs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/nextjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeedu/imersao-fc6/19a03481f3ead5bf4fe22e1c5447de842b29829b/img/nextjs.png -------------------------------------------------------------------------------- /k8s/golang/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: golang 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: golang 9 | template: 10 | metadata: 11 | labels: 12 | app: golang 13 | spec: 14 | containers: 15 | - name: golang 16 | image: argentinaluiz/imersao6-golang 17 | envFrom: 18 | - secretRef: 19 | name: golang-secret 20 | -------------------------------------------------------------------------------- /k8s/golang/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: golang-secret 5 | type: Opaque 6 | data: 7 | MAIL_HOST: c210cC5zZW5kZ3JpZC5uZXQ= 8 | MAIL_PORT: NDY1 9 | MAIL_USER: YXBpa2V5 10 | MAIL_PASSWORD: U0cuTjhQTEx6a2FRRktpdGFLNDJsQVI4US5JWlhVUDNwaVVrZG5QVUctWVdLdkN3RFB3WTFONDFEdlkxU1FENWNtSTFV 11 | MAIL_FROM: YXJnZW50aW5hbHVpekBnbWFpbC5jb20= 12 | BOOTSTRAP_SERVERS: cGtjLXltcnE3LnVzLWVhc3QtMi5hd3MuY29uZmx1ZW50LmNsb3VkOjkwOTI= 13 | SECURITY_PROTOCOL: U0FTTF9TU0w= 14 | SASL_MECHANISMS: UExBSU4= 15 | SASL_USERNAME: WE1OSVJOVUpYSTNFN0dDQw== 16 | SASL_PASSWORD: Q2RhVGtXMzJydERvdXRRQ2NDclhIZGxvbm1IamRHYzcxTXkzaXdvWVV4T0xIcXNuTzJSbjVYS2FTK0ZkbUV1Wg== 17 | -------------------------------------------------------------------------------- /k8s/nestjs/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nestjs 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: nestjs 9 | template: 10 | metadata: 11 | labels: 12 | app: nestjs 13 | spec: 14 | containers: 15 | - name: nestjs 16 | image: argentinaluiz/imersao6-nestjs 17 | envFrom: 18 | - secretRef: 19 | name: nestjs-secret 20 | ports: 21 | - containerPort: 3000 22 | -------------------------------------------------------------------------------- /k8s/nestjs/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: nestjs-secret 5 | type: Opaque 6 | data: 7 | NEXT_HOST: aHR0cDovL2xvY2FsaG9zdDozMDAx 8 | KAFKA_HOST: cGtjLXltcnE3LnVzLWVhc3QtMi5hd3MuY29uZmx1ZW50LmNsb3VkOjkwOTI= 9 | KAFKA_CLIENT_ID: bmVzdA== 10 | KAFKA_CONSUMER_GROUP_ID: bmVzdA== 11 | KAFKA_SASL_USERNAME: WE1OSVJOVUpYSTNFN0dDQw== 12 | KAFKA_SASL_PASSWORD: Q2RhVGtXMzJydERvdXRRQ2NDclhIZGxvbm1IamRHYzcxTXkzaXdvWVV4T0xIcXNuTzJSbjVYS2FTK0ZkbUV1Wg== 13 | KAFKA_CONNECTION_TIMEOUT: NDUwMDA= 14 | KAFKA_USE_SSL: dHJ1ZQ== 15 | MONGO_DSN: bW9uZ29kYitzcnY6Ly9yb290OnJvb3RAY2x1c3RlcjAubnVydm8ubW9uZ29kYi5uZXQvYW5hbHl0aWNzP3JldHJ5V3JpdGVzPXRydWUmdz1tYWpvcml0eQ== 16 | REDIS_HOST: cmVkaXMtMTgzODYuYzI0MC51cy1lYXN0LTEtMy5lYzIuY2xvdWQucmVkaXNsYWJzLmNvbQ== 17 | REDIS_PORT: MTgzODY= 18 | REDIS_PASSWORD: WVRmNkwyYjdNUEJHQTFKUm8xclhFWVdFT2xKQTA2ZXQ= 19 | -------------------------------------------------------------------------------- /k8s/nestjs/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nestjs 5 | spec: 6 | selector: 7 | app: nestjs 8 | ports: 9 | - port: 80 10 | targetPort: 3000 11 | -------------------------------------------------------------------------------- /k8s/nextjs/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nextjs 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: nextjs 9 | template: 10 | metadata: 11 | labels: 12 | app: nextjs 13 | spec: 14 | containers: 15 | - name: nextjs 16 | image: argentinaluiz/imersao6-next.js 17 | envFrom: 18 | - secretRef: 19 | name: nextjs-secret 20 | ports: 21 | - containerPort: 3000 22 | -------------------------------------------------------------------------------- /k8s/nextjs/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: nextjs-secret 5 | type: Opaque 6 | data: 7 | NEXT_PUBLIC_NEST_HOST: aHR0cDovL2xvY2FsaG9zdDozMDAw 8 | -------------------------------------------------------------------------------- /k8s/nextjs/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: nextjs 5 | spec: 6 | selector: 7 | app: nextjs 8 | ports: 9 | - port: 80 10 | targetPort: 3000 11 | -------------------------------------------------------------------------------- /kafka/README.md: -------------------------------------------------------------------------------- 1 | # Imersão Full Stack & FullCycle 6.0 - Fincycle - Kafka e Kafka Connect 2 | 3 | ## Descrição 4 | 5 | Repositório do Kafka e Kafka Connect 6 | 7 | ## Rodar a aplicação 8 | 9 | ### Configurar /etc/hosts 10 | 11 | A comunicação entre as aplicações se dá de forma direta através da rede da máquina. 12 | Para isto é necessário configurar um endereços que todos os containers Docker consigam acessar. 13 | 14 | Acrescente no seu /etc/hosts (para Windows o caminho é C:\Windows\system32\drivers\etc\hosts): 15 | ``` 16 | 127.0.0.1 host.docker.internal 17 | ``` 18 | Em todos os sistemas operacionais é necessário abrir o programa para editar o *hosts* como Administrator da máquina ou root. 19 | 20 | Execute o comando: 21 | 22 | ``` 23 | docker-compose up 24 | ``` 25 | 26 | Espere um pouco antes de testar o Control Center no endereço: `http://localhost:9021`. 27 | Configure um client no painel de developers do Twitter: [https://developer.twitter.com/en](https://developer.twitter.com/en), antes de criar um connector do Twitter no painel do Kafka Connect. 28 | 29 | Crie o connector do Twitter, depois o do MongoDB (necessário iniciar o serviço do MongoDB do `docker-compose.yaml` do Nest.js). 30 | 31 | Verifique se o tópico `tweets` foi criado com os novos tweets capturados (lembre-se de não deixar ativo muito tempo para testar, senão o Twitter pode bloquear). 32 | 33 | Toda vez que parar os containers do Kafka, é necessário executar o comando `docker-compose down` antes. 34 | 35 | 36 | ### Para Windows 37 | 38 | Siga o guia rápido de instalação: [https://github.com/codeedu/wsl2-docker-quickstart](https://github.com/codeedu/wsl2-docker-quickstart) 39 | -------------------------------------------------------------------------------- /kafka/connectors/sink-mongo-twitter.properties: -------------------------------------------------------------------------------- 1 | name = mongo-sink-from-twitter 2 | connector.class = com.mongodb.kafka.connect.MongoSinkConnector 3 | task.max = 1 4 | topics = tweets 5 | connection.uri = mongodb://root:root@host.docker.internal/ 6 | database = analytics 7 | value.converter = org.apache.kafka.connect.json.JsonConverter 8 | value.converter.schemas.enable = false 9 | transforms = extractValue 10 | transforms.extractValue.type = org.apache.kafka.connect.transforms.ExtractField$Value 11 | transforms.extractValue.field = payload -------------------------------------------------------------------------------- /kafka/connectors/source-twitter.properties: -------------------------------------------------------------------------------- 1 | name = twitter 2 | connector.class = com.github.jcustenborder.kafka.connect.twitter.TwitterSourceConnector 3 | twitter.oauth.consumerKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXX 4 | twitter.oauth.consumerSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXX 5 | twitter.oauth.accessToken = XXXXXXXXXXXXXXXXXXXXXXXXXXXX 6 | twitter.oauth.accessTokenSecret = XXXXXXXXXXXXXXXXXXXXXXXXXXXX 7 | filter.keywords = bbb 8 | kafka.status.topic = tweets 9 | process.deletes = false -------------------------------------------------------------------------------- /kafka/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | zookeeper: 4 | image: confluentinc/cp-zookeeper:latest 5 | environment: 6 | ZOOKEEPER_CLIENT_PORT: 2181 7 | 8 | kafka: 9 | image: confluentinc/cp-kafka:latest 10 | depends_on: 11 | - zookeeper 12 | ports: 13 | - 9092:9092 14 | - 9094:9094 15 | environment: 16 | KAFKA_BROKER_ID: 1 17 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 18 | KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 19 | KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL 20 | KAFKA_LISTENERS: INTERNAL://:9092,OUTSIDE://:9094 21 | KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:9092,OUTSIDE://host.docker.internal:9094 22 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT 23 | extra_hosts: 24 | - "host.docker.internal:172.17.0.1" 25 | 26 | control-center: 27 | image: confluentinc/cp-enterprise-control-center:6.0.1 28 | hostname: control-center 29 | depends_on: 30 | - kafka 31 | - kafka-connect 32 | ports: 33 | - "9021:9021" 34 | environment: 35 | CONTROL_CENTER_BOOTSTRAP_SERVERS: 'kafka:9092' 36 | CONTROL_CENTER_REPLICATION_FACTOR: 1 37 | CONTROL_CENTER_CONNECT_CLUSTER: http://kafka-connect:8083 38 | PORT: 9021 39 | 40 | kafka-connect: 41 | image: confluentinc/cp-kafka-connect-base:6.0.0 42 | container_name: kafka-connect 43 | depends_on: 44 | - zookeeper 45 | - kafka 46 | ports: 47 | - 8083:8083 48 | environment: 49 | CONNECT_BOOTSTRAP_SERVERS: "kafka:9092" 50 | CONNECT_REST_PORT: 8083 51 | CONNECT_GROUP_ID: kafka-connect 52 | CONNECT_CONFIG_STORAGE_TOPIC: _connect-configs 53 | CONNECT_OFFSET_STORAGE_TOPIC: _connect-offsets 54 | CONNECT_STATUS_STORAGE_TOPIC: _connect-status 55 | CONNECT_KEY_CONVERTER: org.apache.kafka.connect.storage.StringConverter 56 | CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter 57 | CONNECT_INTERNAL_KEY_CONVERTER: "org.apache.kafka.connect.json.JsonConverter" 58 | CONNECT_INTERNAL_VALUE_CONVERTER: "org.apache.kafka.connect.json.JsonConverter" 59 | CONNECT_REST_ADVERTISED_HOST_NAME: "kafka-connect" 60 | CONNECT_LOG4J_ROOT_LOGLEVEL: "INFO" 61 | CONNECT_LOG4J_LOGGERS: "org.apache.kafka.connect.runtime.rest=WARN,org.reflections=ERROR" 62 | CONNECT_LOG4J_APPENDER_STDOUT_LAYOUT_CONVERSIONPATTERN: "[%d] %p %X{connector.context}%m (%c:%L)%n" 63 | CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: "1" 64 | CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: "1" 65 | CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: "1" 66 | # # Optional settings to include to support Confluent Control Center 67 | # CONNECT_PRODUCER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringProducerInterceptor" 68 | # CONNECT_CONSUMER_INTERCEPTOR_CLASSES: "io.confluent.monitoring.clients.interceptor.MonitoringConsumerInterceptor" 69 | # --------------- 70 | CONNECT_PLUGIN_PATH: /usr/share/java,/usr/share/confluent-hub-components,/data/connect-jars 71 | # In the command section, $ are replaced with $$ to avoid the error 'Invalid interpolation format for "command" option' 72 | command: 73 | - bash 74 | - -c 75 | - | 76 | echo "Installing Connector" 77 | confluent-hub install --no-prompt mongodb/kafka-connect-mongodb:1.5.0 78 | confluent-hub install --no-prompt jcustenborder/kafka-connect-twitter:0.3.33 79 | # 80 | echo "Launching Kafka Connect worker" 81 | /etc/confluent/docker/run & 82 | # 83 | sleep infinity 84 | extra_hosts: 85 | - "host.docker.internal:172.17.0.1" -------------------------------------------------------------------------------- /nestjs/.docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -f ".env" ]; then 4 | cp .env.example .env 5 | fi 6 | 7 | npm install 8 | 9 | npm run start:dev -------------------------------------------------------------------------------- /nestjs/.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules/ 3 | dist/ 4 | .docker/dbdata 5 | .env -------------------------------------------------------------------------------- /nestjs/.env.example: -------------------------------------------------------------------------------- 1 | MONGO_DSN=mongodb://root:root@db/analytics?authSource=admin 2 | 3 | REDIS_HOST=redis 4 | REDIS_PORT=6379 5 | REDIS_PASSWORD= 6 | 7 | NEXT_HOST=http://localhost:3001 8 | 9 | KAFKA_CLIENT_ID=nest 10 | KAFKA_HOST=host.docker.internal:9094 11 | KAFKA_USE_SSL=false 12 | KAFKA_CONSUMER_GROUP_ID=nest 13 | KAFKA_SASL_USERNAME= 14 | KAFKA_SASL_PASSWORD= 15 | KAFKA_CONNECTION_TIMEOUT=45000 -------------------------------------------------------------------------------- /nestjs/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@typescript-eslint/parser', 3 | parserOptions: { 4 | project: 'tsconfig.json', 5 | sourceType: 'module', 6 | }, 7 | plugins: ['@typescript-eslint/eslint-plugin'], 8 | extends: [ 9 | 'plugin:@typescript-eslint/recommended', 10 | 'plugin:prettier/recommended', 11 | ], 12 | root: true, 13 | env: { 14 | node: true, 15 | jest: true, 16 | }, 17 | ignorePatterns: ['.eslintrc.js'], 18 | rules: { 19 | '@typescript-eslint/interface-name-prefix': 'off', 20 | '@typescript-eslint/explicit-function-return-type': 'off', 21 | '@typescript-eslint/explicit-module-boundary-types': 'off', 22 | '@typescript-eslint/no-explicit-any': 'off', 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /nestjs/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled output 2 | /dist 3 | /node_modules 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | pnpm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # OS 15 | .DS_Store 16 | 17 | # Tests 18 | /coverage 19 | /.nyc_output 20 | 21 | # IDEs and editors 22 | /.idea 23 | .project 24 | .classpath 25 | .c9/ 26 | *.launch 27 | .settings/ 28 | *.sublime-workspace 29 | 30 | # IDE - VSCode 31 | .vscode/* 32 | !.vscode/settings.json 33 | !.vscode/tasks.json 34 | !.vscode/launch.json 35 | !.vscode/extensions.json 36 | 37 | .docker/dbdata/ 38 | .env 39 | 40 | .history/ -------------------------------------------------------------------------------- /nestjs/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } -------------------------------------------------------------------------------- /nestjs/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.activeBackground": "#e65072", 4 | "activityBar.activeBorder": "#4bdf20", 5 | "activityBar.background": "#e65072", 6 | "activityBar.foreground": "#15202b", 7 | "activityBar.inactiveForeground": "#15202b99", 8 | "activityBarBadge.background": "#4bdf20", 9 | "activityBarBadge.foreground": "#15202b", 10 | "sash.hoverBorder": "#e65072", 11 | "statusBar.background": "#e65072", 12 | "statusBar.foreground": "#15202b", 13 | "statusBarItem.hoverBackground": "#e0234e", 14 | "statusBarItem.remoteBackground": "#e65072", 15 | "statusBarItem.remoteForeground": "#15202b", 16 | "tab.activeBorder": "#e65072", 17 | "titleBar.activeBackground": "#e65072", 18 | "titleBar.activeForeground": "#15202b", 19 | "titleBar.inactiveBackground": "#e6507299", 20 | "titleBar.inactiveForeground": "#15202b99" 21 | }, 22 | "peacock.remoteColor": "#e0234e" 23 | } -------------------------------------------------------------------------------- /nestjs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14.15.4-alpine3.12 2 | 3 | RUN npm install -g @nestjs/cli@8.0.0 4 | 5 | USER node 6 | 7 | WORKDIR /home/node/app -------------------------------------------------------------------------------- /nestjs/Dockerfile.prod: -------------------------------------------------------------------------------- 1 | FROM node:14.15.4-slim 2 | 3 | USER node 4 | 5 | RUN mkdir -p /home/node/app 6 | 7 | WORKDIR /home/node/app 8 | 9 | COPY --chown=node package*.json ./ 10 | 11 | RUN npm install 12 | 13 | COPY --chown=node ./ . 14 | 15 | RUN npm run build 16 | 17 | EXPOSE 3000 18 | 19 | CMD ["npm", "run", "start:prod"] -------------------------------------------------------------------------------- /nestjs/README.md: -------------------------------------------------------------------------------- 1 | [](Nest.js) 2 | 3 | # Imersão Full Stack & FullCycle 6.0 - Fincycle - Back-end do monitoramento de tweets 4 | 5 | ## Descrição 6 | 7 | Repositório do back-end do monitoramento de tweets feito com Nest.js 8 | 9 | **Importante**: A aplicação do Apache Kafka primeiro. 10 | 11 | ## Rodar a aplicação 12 | 13 | ### Configurar /etc/hosts 14 | 15 | A comunicação entre as aplicações se dá de forma direta através da rede da máquina. 16 | Para isto é necessário configurar um endereços que todos os containers Docker consigam acessar. 17 | 18 | Acrescente no seu /etc/hosts (para Windows o caminho é C:\Windows\system32\drivers\etc\hosts): 19 | ``` 20 | 127.0.0.1 host.docker.internal 21 | ``` 22 | Em todos os sistemas operacionais é necessário abrir o programa para editar o *hosts* como Administrator da máquina ou root. 23 | 24 | 25 | Execute o comando: 26 | 27 | ``` 28 | docker-compose up 29 | ``` 30 | 31 | Acessar http://localhost:3000. Use o arquivo `api.http` para testar a API. 32 | 33 | Quer configurar um ambiente de desenvolvimento produtivo? Veja o vídeo: [https://www.youtube.com/watch?v=bniD6dehPCQ](https://www.youtube.com/watch?v=bniD6dehPCQ) 34 | 35 | ### Para Windows 36 | 37 | Siga o guia rápido de instalação: [https://github.com/codeedu/wsl2-docker-quickstart](https://github.com/codeedu/wsl2-docker-quickstart) 38 | -------------------------------------------------------------------------------- /nestjs/api.http: -------------------------------------------------------------------------------- 1 | GET http://localhost:3000/tweets 2 | 3 | ### 4 | POST http://localhost:3000/tweets 5 | Content-Type: application/json 6 | 7 | { 8 | "Text": "Imersão começou.....", 9 | "User": { 10 | "Name": "Luiz Carlos" 11 | } 12 | } 13 | 14 | ### 15 | GET http://localhost:3000/mail-list 16 | 17 | 18 | ### 19 | POST http://localhost:3000/mail-list 20 | Content-Type: application/json 21 | 22 | { 23 | "emails": ["user1@test.com", "user2@test.com", "user3@test.com"] 24 | } -------------------------------------------------------------------------------- /nestjs/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | app: 5 | build: . 6 | entrypoint: .docker/entrypoint.sh 7 | volumes: 8 | - .:/home/node/app 9 | ports: 10 | - 3000:3000 11 | depends_on: 12 | - db 13 | extra_hosts: 14 | - "host.docker.internal:172.17.0.1" 15 | 16 | db: 17 | image: mongo:5.0.5 18 | restart: always 19 | volumes: 20 | - ./.docker/dbdata:/data/db 21 | ports: 22 | - 27017:27017 23 | environment: 24 | - MONGO_INITDB_ROOT_USERNAME=root 25 | - MONGO_INITDB_ROOT_PASSWORD=root 26 | - MONGO_INITDB_DATABASE=analytics 27 | 28 | mongo-express: 29 | image: mongo-express:0.54.0 30 | restart: always 31 | ports: 32 | - 8081:8081 33 | environment: 34 | - ME_CONFIG_MONGODB_SERVER=db 35 | - ME_CONFIG_MONGODB_AUTH_USERNAME=root 36 | - ME_CONFIG_MONGODB_AUTH_PASSWORD=root 37 | - ME_CONFIG_MONGODB_ADMINUSERNAME=root 38 | - ME_CONFIG_MONGODB_ADMINPASSWORD=root 39 | depends_on: 40 | - db 41 | 42 | redis: 43 | image: redis:6.2.6-alpine3.14 44 | -------------------------------------------------------------------------------- /nestjs/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "collection": "@nestjs/schematics", 3 | "sourceRoot": "src" 4 | } 5 | -------------------------------------------------------------------------------- /nestjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nestjs", 3 | "version": "0.0.1", 4 | "description": "", 5 | "author": "", 6 | "private": true, 7 | "license": "UNLICENSED", 8 | "scripts": { 9 | "prebuild": "rimraf dist", 10 | "build": "nest build", 11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", 12 | "start": "nest start", 13 | "start:dev": "nest start --watch", 14 | "start:debug": "nest start --debug --watch", 15 | "start:prod": "node dist/main", 16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", 17 | "test": "jest", 18 | "test:watch": "jest --watch", 19 | "test:cov": "jest --coverage", 20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", 21 | "test:e2e": "jest --config ./test/jest-e2e.json" 22 | }, 23 | "dependencies": { 24 | "@nestjs/bull": "^0.4.2", 25 | "@nestjs/common": "^8.0.0", 26 | "@nestjs/config": "^1.1.6", 27 | "@nestjs/core": "^8.0.0", 28 | "@nestjs/mapped-types": "*", 29 | "@nestjs/microservices": "^8.2.6", 30 | "@nestjs/mongoose": "^9.0.2", 31 | "@nestjs/platform-express": "^8.0.0", 32 | "@nestjs/schedule": "^1.0.2", 33 | "bull": "^4.5.0", 34 | "cache-manager": "^3.6.0", 35 | "cache-manager-redis-store": "^2.0.0", 36 | "kafkajs": "^1.15.0", 37 | "mongodb": "^4.3.1", 38 | "mongoose": "^6.2.0", 39 | "reflect-metadata": "^0.1.13", 40 | "rimraf": "^3.0.2", 41 | "rxjs": "^7.2.0" 42 | }, 43 | "devDependencies": { 44 | "@nestjs/cli": "^8.0.0", 45 | "@nestjs/schematics": "^8.0.0", 46 | "@nestjs/testing": "^8.0.0", 47 | "@types/bull": "^3.15.7", 48 | "@types/cache-manager": "^3.4.2", 49 | "@types/cron": "^1.7.3", 50 | "@types/express": "^4.17.13", 51 | "@types/jest": "27.0.2", 52 | "@types/node": "^16.0.0", 53 | "@types/supertest": "^2.0.11", 54 | "@typescript-eslint/eslint-plugin": "^5.0.0", 55 | "@typescript-eslint/parser": "^5.0.0", 56 | "eslint": "^8.0.1", 57 | "eslint-config-prettier": "^8.3.0", 58 | "eslint-plugin-prettier": "^4.0.0", 59 | "jest": "^27.2.5", 60 | "prettier": "^2.3.2", 61 | "source-map-support": "^0.5.20", 62 | "supertest": "^6.1.3", 63 | "ts-jest": "^27.0.3", 64 | "ts-loader": "^9.2.3", 65 | "ts-node": "^10.0.0", 66 | "tsconfig-paths": "^3.10.1", 67 | "typescript": "^4.3.5" 68 | }, 69 | "jest": { 70 | "moduleFileExtensions": [ 71 | "js", 72 | "json", 73 | "ts" 74 | ], 75 | "rootDir": "src", 76 | "testRegex": ".*\\.spec\\.ts$", 77 | "transform": { 78 | "^.+\\.(t|j)s$": "ts-jest" 79 | }, 80 | "collectCoverageFrom": [ 81 | "**/*.(t|j)s" 82 | ], 83 | "coverageDirectory": "../coverage", 84 | "testEnvironment": "node" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /nestjs/src/app.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { AppController } from './app.controller'; 3 | import { AppService } from './app.service'; 4 | 5 | describe('AppController', () => { 6 | let appController: AppController; 7 | 8 | beforeEach(async () => { 9 | const app: TestingModule = await Test.createTestingModule({ 10 | controllers: [AppController], 11 | providers: [AppService], 12 | }).compile(); 13 | 14 | appController = app.get(AppController); 15 | }); 16 | 17 | describe('root', () => { 18 | it('should return "Hello World!"', () => { 19 | expect(appController.getHello()).toBe('Hello World!'); 20 | }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /nestjs/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | 4 | @Controller('/prefixo') 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get('/test') 9 | getHello(): string { 10 | return this.appService.getHello(); 11 | } 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /nestjs/src/app.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { MongooseModule } from '@nestjs/mongoose'; 3 | import { ScheduleModule } from '@nestjs/schedule'; 4 | import { AppController } from './app.controller'; 5 | import { AppService } from './app.service'; 6 | import { TweetsModule } from './tweets/tweets.module'; 7 | import { MailListModule } from './mail-list/mail-list.module'; 8 | import { BullModule } from '@nestjs/bull'; 9 | import { ConfigModule } from '@nestjs/config'; 10 | //ES7 Decorators 11 | @Module({ 12 | imports: [ 13 | ConfigModule.forRoot({ isGlobal: true }), 14 | BullModule.forRoot({ 15 | redis: { 16 | host: process.env.REDIS_HOST, 17 | port: parseInt(process.env.REDIS_PORT), 18 | password: process.env.REDIS_PASSWORD 19 | }, 20 | }), 21 | MongooseModule.forRoot(process.env.MONGO_DSN, { 22 | useNewUrlParser: true, 23 | }), 24 | ScheduleModule.forRoot(), 25 | TweetsModule, 26 | MailListModule, 27 | ], 28 | controllers: [AppController], 29 | providers: [AppService], 30 | }) 31 | export class AppModule {} 32 | -------------------------------------------------------------------------------- /nestjs/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello(): string { 6 | return 'Hello World!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/dto/create-mail-list.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateMailListDto { 2 | emails: string[]; 3 | } 4 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/dto/update-mail-list.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateMailListDto } from './create-mail-list.dto'; 3 | 4 | export class UpdateMailListDto extends PartialType(CreateMailListDto) {} 5 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/mail-list.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { MailListController } from './mail-list.controller'; 3 | import { MailListService } from './mail-list.service'; 4 | 5 | describe('MailListController', () => { 6 | let controller: MailListController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [MailListController], 11 | providers: [MailListService], 12 | }).compile(); 13 | 14 | controller = module.get(MailListController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/mail-list.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Post, Body, Res, HttpStatus } from '@nestjs/common'; 2 | import { MailListService } from './mail-list.service'; 3 | import { CreateMailListDto } from './dto/create-mail-list.dto'; 4 | 5 | @Controller('mail-list') 6 | export class MailListController { 7 | constructor(private readonly mailListService: MailListService) {} 8 | 9 | @Post() 10 | create(@Body() createMailListDto: CreateMailListDto) { 11 | return this.mailListService.create(createMailListDto); 12 | } 13 | 14 | @Get() 15 | async findOne(@Res() res) { 16 | const mail = await this.mailListService.findOne(); 17 | return !mail 18 | ? res.status(HttpStatus.NO_CONTENT).json(null) 19 | : res.json(mail); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/mail-list.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { MailListService } from './mail-list.service'; 3 | import { MailListController } from './mail-list.controller'; 4 | import { MongooseModule } from '@nestjs/mongoose'; 5 | import { MailList, MailListSchema } from './schemas/mail-list.schema'; 6 | import { SendMailTweetsJob } from './send-mail-tweets.job'; 7 | import { ClientKafka, ClientsModule, Transport } from '@nestjs/microservices'; 8 | 9 | @Module({ 10 | imports: [ 11 | MongooseModule.forFeature([ 12 | { name: MailList.name, schema: MailListSchema }, 13 | ]), 14 | ClientsModule.registerAsync([ 15 | { 16 | name: 'KAFKA_SERVICE', 17 | useFactory: () => ({ 18 | transport: Transport.KAFKA, 19 | options: { 20 | client: { 21 | clientId: process.env.KAFKA_CLIENT_ID, 22 | connectionTimeout: parseInt(process.env.KAFKA_CONNECTION_TIMEOUT), 23 | brokers: [process.env.KAFKA_HOST], 24 | ssl: process.env.KAFKA_USE_SSL === 'true', 25 | ...(process.env.KAFKA_SASL_USERNAME && 26 | process.env.KAFKA_SASL_USERNAME !== '' && 27 | process.env.KAFKA_SASL_PASSWORD && 28 | process.env.KAFKA_SASL_PASSWORD !== '' && { 29 | sasl: { 30 | mechanism: 'plain', 31 | username: process.env.KAFKA_SASL_USERNAME, 32 | password: process.env.KAFKA_SASL_PASSWORD, 33 | }, 34 | }), 35 | }, 36 | }, 37 | consumer: { 38 | groupId: process.env.KAFKA_CONSUMER_GROUP_ID, 39 | }, 40 | }), 41 | }, 42 | ]), 43 | ], 44 | controllers: [MailListController], 45 | providers: [ 46 | MailListService, 47 | SendMailTweetsJob, 48 | { 49 | provide: 'KAFKA_PRODUCER', 50 | useFactory: async (kafkaService: ClientKafka) => { 51 | return kafkaService.connect(); 52 | }, 53 | inject: ['KAFKA_SERVICE'], 54 | }, 55 | ], 56 | }) 57 | export class MailListModule {} 58 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/mail-list.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { MailListService } from './mail-list.service'; 3 | 4 | describe('MailListService', () => { 5 | let service: MailListService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [MailListService], 10 | }).compile(); 11 | 12 | service = module.get(MailListService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/mail-list.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { InjectModel } from '@nestjs/mongoose'; 3 | import { Model } from 'mongoose'; 4 | import { CreateMailListDto } from './dto/create-mail-list.dto'; 5 | import { MailList, MailListDocument } from './schemas/mail-list.schema'; 6 | 7 | @Injectable() 8 | export class MailListService { 9 | constructor( 10 | @InjectModel(MailList.name) 11 | private mailListModel: Model, 12 | ) {} 13 | 14 | async create({ emails }: CreateMailListDto) { 15 | const mail = await this.findOne(); 16 | if (!mail) { 17 | return this.mailListModel.create({ emails }); 18 | } 19 | await mail.update({ emails }).exec(); 20 | return this.findOne(); 21 | } 22 | 23 | async findOne() { 24 | const mails = await this.mailListModel.find().exec(); 25 | return mails.length ? mails[0] : null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/schemas/mail-list.schema.ts: -------------------------------------------------------------------------------- 1 | import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; 2 | import { Document, Schema as MongooseSchema } from 'mongoose'; 3 | 4 | @Schema() 5 | export class MailList { 6 | @Prop({ type: MongooseSchema.Types.ObjectId }) 7 | id: string; 8 | 9 | @Prop({ type: [String] }) 10 | emails: string[]; 11 | } 12 | 13 | export type MailListDocument = MailList & Document; 14 | 15 | export const MailListSchema = SchemaFactory.createForClass(MailList); 16 | -------------------------------------------------------------------------------- /nestjs/src/mail-list/send-mail-tweets.job.ts: -------------------------------------------------------------------------------- 1 | import { Job } from 'bull'; 2 | import { Process, Processor } from '@nestjs/bull'; 3 | import { MailListService } from './mail-list.service'; 4 | import { Producer } from '@nestjs/microservices/external/kafka.interface'; 5 | import { ConfigService } from '@nestjs/config'; 6 | import { Inject } from '@nestjs/common'; 7 | 8 | @Processor('emails') 9 | export class SendMailTweetsJob { 10 | constructor( 11 | private mailListService: MailListService, 12 | @Inject('KAFKA_PRODUCER') 13 | private kafkaProducer: Producer, 14 | private configService: ConfigService, 15 | ) {} 16 | 17 | @Process() 18 | async handle(job: Job) { 19 | const mailList = await this.mailListService.findOne(); 20 | const link = this.configService.get('NEXT_HOST'); 21 | await this.kafkaProducer.send({ 22 | topic: 'emails', 23 | messages: [ 24 | { 25 | key: 'emails', 26 | value: JSON.stringify({ 27 | subject: 'Novos tweets encontrados', 28 | body: `Acesse o link Clique aqui`, 29 | emails: mailList.emails, 30 | }), 31 | }, 32 | ], 33 | }); 34 | console.log(mailList.emails); 35 | console.log('enviou mensagem para o micro do Wesley'); 36 | } 37 | } 38 | 39 | //nest Kafka golang 40 | -------------------------------------------------------------------------------- /nestjs/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | 4 | async function bootstrap() { 5 | const app = await NestFactory.create(AppModule, { cors: true }); 6 | await app.listen(3000); 7 | } 8 | bootstrap(); 9 | 10 | //Nestjs - Module 11 | -------------------------------------------------------------------------------- /nestjs/src/tweets/check-new-tweets/check-new-tweets.task.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { CheckNewTweetsTask } from './check-new-tweets.task'; 3 | 4 | describe('CheckNewTweetsTask', () => { 5 | let service: CheckNewTweetsTask; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [CheckNewTweetsTask], 10 | }).compile(); 11 | 12 | service = module.get(CheckNewTweetsTask); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /nestjs/src/tweets/check-new-tweets/check-new-tweets.task.ts: -------------------------------------------------------------------------------- 1 | import { TweetsService } from './../tweets.service'; 2 | import { CACHE_MANAGER, Inject, Injectable } from '@nestjs/common'; 3 | import { Interval } from '@nestjs/schedule'; 4 | import { Cache } from 'cache-manager'; 5 | import { Queue } from 'bull'; 6 | import { InjectQueue } from '@nestjs/bull'; 7 | 8 | @Injectable() 9 | export class CheckNewTweetsTask { 10 | private limit = 10; 11 | 12 | constructor( 13 | private tweetService: TweetsService, 14 | @Inject(CACHE_MANAGER) 15 | private cache: Cache, 16 | @InjectQueue('emails') 17 | private emailsQueue: Queue, 18 | ) {} 19 | 20 | @Interval(5000) 21 | async handle() { 22 | console.log('procurando tweets...'); 23 | let offset = await this.cache.get('tweet-offset'); 24 | offset = offset === undefined || offset === null ? 0 : offset; 25 | 26 | console.log(`offset: ${offset}`); 27 | 28 | const tweets = await this.tweetService.findAll({ 29 | offset, 30 | limit: this.limit, 31 | }); 32 | 33 | console.log(`tweets count: ${tweets.length}`); 34 | 35 | if (tweets.length === this.limit) { 36 | console.log('achou mais tweets'); 37 | 38 | await this.cache.set('tweet-offset', offset + this.limit, { 39 | ttl: 1 * 60 * 10, 40 | }); 41 | 42 | this.emailsQueue.add({}); //kafka 43 | } 44 | } 45 | } 46 | 47 | // page 1 2 3 48 | 49 | // select * from tabela limit 0, 15 15, 15 50 | 51 | // fila de processamento 52 | 53 | // redis 54 | -------------------------------------------------------------------------------- /nestjs/src/tweets/dto/create-tweet.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateTweetDto {} 2 | -------------------------------------------------------------------------------- /nestjs/src/tweets/dto/update-tweet.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateTweetDto } from './create-tweet.dto'; 3 | 4 | export class UpdateTweetDto extends PartialType(CreateTweetDto) {} 5 | -------------------------------------------------------------------------------- /nestjs/src/tweets/schemas/tweet.schema.ts: -------------------------------------------------------------------------------- 1 | import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; 2 | import { Int32 } from 'mongodb'; 3 | import { Document, Schema as MongooseSchema } from 'mongoose'; 4 | 5 | export type TweetDocument = Tweet & Document; 6 | 7 | @Schema() 8 | export class TweetUser { 9 | @Prop({ type: MongooseSchema.Types.ObjectId }) 10 | Id: string; 11 | @Prop() 12 | Name: string; 13 | @Prop() 14 | ScreenName: string; 15 | @Prop({ type: MongooseSchema.Types.Mixed }) 16 | Location: any; 17 | @Prop() 18 | Description: string; 19 | @Prop({ type: Boolean }) 20 | ContributorsEnabled: boolean; 21 | @Prop() 22 | ProfileImageURL: string; 23 | @Prop() 24 | BiggerProfileImageURL: string; 25 | @Prop() 26 | MiniProfileImageURL: string; 27 | @Prop() 28 | OriginalProfileImageURL: string; 29 | @Prop() 30 | ProfileImageURLHttps: string; 31 | @Prop() 32 | BiggerProfileImageURLHttps: string; 33 | @Prop() 34 | MiniProfileImageURLHttps: string; 35 | @Prop() 36 | OriginalProfileImageURLHttps: string; 37 | @Prop({ type: Boolean }) 38 | DefaultProfileImage: boolean; 39 | @Prop() 40 | URL: string; 41 | @Prop({ type: Boolean }) 42 | Protected: boolean; 43 | @Prop() 44 | FollowersCount: number; 45 | @Prop() 46 | ProfileBackgroundColor: string; 47 | @Prop() 48 | ProfileTextColor: string; 49 | @Prop() 50 | ProfileLinkColor: string; 51 | @Prop() 52 | ProfileSidebarFillColor: string; 53 | @Prop() 54 | ProfileSidebarBorderColor: string; 55 | @Prop({ type: Boolean }) 56 | ProfileUseBackgroundImage: boolean; 57 | @Prop({ type: Boolean }) 58 | DefaultProfile: boolean; 59 | @Prop({ type: Boolean }) 60 | ShowAllInlineMedia: boolean; 61 | @Prop() 62 | FriendsCount: number; 63 | @Prop() 64 | CreatedAt: number; 65 | @Prop() 66 | FavouritesCount: number; 67 | @Prop() 68 | UtcOffset: number; 69 | @Prop() 70 | TimeZone: string; 71 | @Prop() 72 | ProfileBackgroundImageURL: string; 73 | @Prop() 74 | ProfileBackgroundImageUrlHttps: string; 75 | @Prop() 76 | ProfileBannerURL: string; 77 | @Prop() 78 | ProfileBannerRetinaURL: string; 79 | @Prop() 80 | ProfileBannerIPadURL: string; 81 | @Prop() 82 | ProfileBannerIPadRetinaURL: string; 83 | @Prop() 84 | ProfileBannerMobileURL: string; 85 | @Prop() 86 | ProfileBannerMobileRetinaURL: string; 87 | @Prop() 88 | ProfileBackgroundTiled: boolean; 89 | @Prop() 90 | Lang: string; 91 | @Prop() 92 | StatusesCount: number; 93 | @Prop({ type: Boolean }) 94 | GeoEnabled: boolean; 95 | @Prop({ type: Boolean }) 96 | Verified: boolean; 97 | @Prop({ type: Boolean }) 98 | Translator: boolean; 99 | @Prop({ type: Boolean }) 100 | ListedCount: number; 101 | @Prop() 102 | FollowRequestSent: boolean; 103 | @Prop() 104 | WithheldInCountries: any[]; 105 | } 106 | 107 | @Schema() 108 | export class Tweet { 109 | @Prop() 110 | Text: string; 111 | 112 | @Prop() 113 | Source: string; 114 | 115 | @Prop({ type: Boolean }) 116 | Truncated: boolean; 117 | 118 | @Prop({ type: MongooseSchema.Types.Number }) 119 | InReplyToStatusId: number; 120 | 121 | @Prop({ type: MongooseSchema.Types.Number }) 122 | InReplyToUserId: number; 123 | 124 | @Prop(String) 125 | InReplyToScreenName: string | null; 126 | 127 | @Prop({ type: MongooseSchema.Types.Mixed }) 128 | GeoLocation: any; 129 | 130 | @Prop({ type: MongooseSchema.Types.Mixed }) 131 | Place: any; 132 | 133 | @Prop({ type: Boolean }) 134 | Favorited: boolean; 135 | @Prop({ type: Boolean }) 136 | Retweeted: boolean; 137 | 138 | @Prop(Int32) 139 | FavoriteCount: number; 140 | 141 | @Prop({ type: Boolean }) 142 | Retweet: false; 143 | @Prop() 144 | Contributors: any[]; 145 | @Prop(Int32) 146 | RetweetCount: number; 147 | @Prop({ type: Boolean }) 148 | RetweetedByMe: boolean; 149 | @Prop() 150 | CurrentUserRetweetId: string; 151 | @Prop({ type: Boolean }) 152 | PossiblySensitive: boolean; 153 | @Prop() 154 | Lang: string; 155 | @Prop() 156 | WithheldInCountries: any[]; 157 | @Prop() 158 | HashtagEntities: any[]; 159 | @Prop() 160 | UserMentionEntities: any[]; 161 | @Prop() 162 | MediaEntities: any[]; 163 | @Prop() 164 | SymbolEntities: any[]; 165 | @Prop() 166 | URLEntities: any[]; 167 | 168 | @Prop() 169 | User: TweetUser; 170 | 171 | @Prop() 172 | CreatedAt: number; 173 | } 174 | 175 | export const TweetSchema = SchemaFactory.createForClass(Tweet); 176 | 177 | 178 | //vendo novos tweets que chegaram no banco de dados 179 | 180 | //10 novos tweets chegarem 181 | 182 | //enviar um novo e-mail para uma listinha -------------------------------------------------------------------------------- /nestjs/src/tweets/tweets.controller.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { TweetsController } from './tweets.controller'; 3 | import { TweetsService } from './tweets.service'; 4 | 5 | describe('TweetsController', () => { 6 | let controller: TweetsController; 7 | 8 | beforeEach(async () => { 9 | const module: TestingModule = await Test.createTestingModule({ 10 | controllers: [TweetsController], 11 | providers: [TweetsService], 12 | }).compile(); 13 | 14 | controller = module.get(TweetsController); 15 | }); 16 | 17 | it('should be defined', () => { 18 | expect(controller).toBeDefined(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /nestjs/src/tweets/tweets.controller.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Controller, 3 | Get, 4 | Post, 5 | Body, 6 | Patch, 7 | Param, 8 | Delete, 9 | } from '@nestjs/common'; 10 | import { TweetsService } from './tweets.service'; 11 | import { CreateTweetDto } from './dto/create-tweet.dto'; 12 | import { UpdateTweetDto } from './dto/update-tweet.dto'; 13 | 14 | @Controller('tweets') 15 | export class TweetsController { 16 | constructor(private readonly tweetsService: TweetsService) {} 17 | 18 | @Post() 19 | create(@Body() createTweetDto: CreateTweetDto) { 20 | return this.tweetsService.create(createTweetDto); 21 | } 22 | 23 | @Get() 24 | findAll() { 25 | return this.tweetsService.findAll(); 26 | } 27 | 28 | @Get(':id') 29 | findOne(@Param('id') id: string) { 30 | return this.tweetsService.findOne(+id); 31 | } 32 | 33 | @Patch(':id') 34 | update(@Param('id') id: string, @Body() updateTweetDto: UpdateTweetDto) { 35 | return this.tweetsService.update(+id, updateTweetDto); 36 | } 37 | 38 | @Delete(':id') 39 | remove(@Param('id') id: string) { 40 | return this.tweetsService.remove(+id); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /nestjs/src/tweets/tweets.module.ts: -------------------------------------------------------------------------------- 1 | import { Tweet, TweetSchema } from './schemas/tweet.schema'; 2 | import { MongooseModule } from '@nestjs/mongoose'; 3 | import { CacheModule, Module } from '@nestjs/common'; 4 | import { TweetsService } from './tweets.service'; 5 | import { TweetsController } from './tweets.controller'; 6 | import { CheckNewTweetsTask } from './check-new-tweets/check-new-tweets.task'; 7 | import * as redisStore from 'cache-manager-redis-store'; 8 | import { BullModule } from '@nestjs/bull'; 9 | 10 | @Module({ 11 | imports: [ 12 | CacheModule.registerAsync({ 13 | useFactory: () => ({ 14 | store: redisStore, 15 | host: process.env.REDIS_HOST, 16 | port: parseInt(process.env.REDIS_PORT), 17 | auth_pass: process.env.REDIS_PASSWORD 18 | }), 19 | }), 20 | MongooseModule.forFeature([{ name: Tweet.name, schema: TweetSchema }]), 21 | BullModule.registerQueue({ 22 | name: 'emails', 23 | }), 24 | ], 25 | controllers: [TweetsController], 26 | providers: [TweetsService, CheckNewTweetsTask], 27 | }) 28 | export class TweetsModule {} 29 | -------------------------------------------------------------------------------- /nestjs/src/tweets/tweets.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { TweetsService } from './tweets.service'; 3 | 4 | describe('TweetsService', () => { 5 | let service: TweetsService; 6 | 7 | beforeEach(async () => { 8 | const module: TestingModule = await Test.createTestingModule({ 9 | providers: [TweetsService], 10 | }).compile(); 11 | 12 | service = module.get(TweetsService); 13 | }); 14 | 15 | it('should be defined', () => { 16 | expect(service).toBeDefined(); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /nestjs/src/tweets/tweets.service.ts: -------------------------------------------------------------------------------- 1 | import { Tweet } from './schemas/tweet.schema'; 2 | import { Injectable } from '@nestjs/common'; 3 | import { InjectModel } from '@nestjs/mongoose'; 4 | import { Model } from 'mongoose'; 5 | import { CreateTweetDto } from './dto/create-tweet.dto'; 6 | import { UpdateTweetDto } from './dto/update-tweet.dto'; 7 | import { TweetDocument } from './schemas/tweet.schema'; 8 | 9 | @Injectable() 10 | export class TweetsService { 11 | constructor( 12 | @InjectModel(Tweet.name) 13 | private tweetModel: Model, 14 | ) {} 15 | 16 | create(createTweetDto: CreateTweetDto) { 17 | return this.tweetModel.create(createTweetDto); 18 | } 19 | 20 | findAll( 21 | { offset, limit }: { offset: number; limit: number } = { 22 | offset: 0, 23 | limit: 50, 24 | }, 25 | ) { 26 | return this.tweetModel 27 | .find() 28 | .skip(offset) 29 | .limit(limit) 30 | .sort({ CreatedAt: -1 }) 31 | .exec(); 32 | } 33 | 34 | findOne(id: number) { 35 | return `This action returns a #${id} tweet`; 36 | } 37 | 38 | update(id: number, updateTweetDto: UpdateTweetDto) { 39 | return `This action updates a #${id} tweet`; 40 | } 41 | 42 | remove(id: number) { 43 | return `This action removes a #${id} tweet`; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /nestjs/test/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { Test, TestingModule } from '@nestjs/testing'; 2 | import { INestApplication } from '@nestjs/common'; 3 | import * as request from 'supertest'; 4 | import { AppModule } from './../src/app.module'; 5 | 6 | describe('AppController (e2e)', () => { 7 | let app: INestApplication; 8 | 9 | beforeEach(async () => { 10 | const moduleFixture: TestingModule = await Test.createTestingModule({ 11 | imports: [AppModule], 12 | }).compile(); 13 | 14 | app = moduleFixture.createNestApplication(); 15 | await app.init(); 16 | }); 17 | 18 | it('/ (GET)', () => { 19 | return request(app.getHttpServer()) 20 | .get('/') 21 | .expect(200) 22 | .expect('Hello World!'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /nestjs/test/jest-e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "moduleFileExtensions": ["js", "json", "ts"], 3 | "rootDir": ".", 4 | "testEnvironment": "node", 5 | "testRegex": ".e2e-spec.ts$", 6 | "transform": { 7 | "^.+\\.(t|j)s$": "ts-jest" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /nestjs/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /nestjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "declaration": true, 5 | "removeComments": true, 6 | "emitDecoratorMetadata": true, 7 | "experimentalDecorators": true, 8 | "allowSyntheticDefaultImports": true, 9 | "target": "es2017", 10 | "sourceMap": true, 11 | "outDir": "./dist", 12 | "baseUrl": "./", 13 | "incremental": true, 14 | "skipLibCheck": true, 15 | "strictNullChecks": false, 16 | "noImplicitAny": false, 17 | "strictBindCallApply": false, 18 | "forceConsistentCasingInFileNames": false, 19 | "noFallthroughCasesInSwitch": false 20 | }, 21 | "include": ["src/"] 22 | } 23 | -------------------------------------------------------------------------------- /nextjs/.docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ ! -f ".env" ]; then 4 | cp .env.example .env 5 | fi 6 | 7 | npm install 8 | 9 | npm run dev -------------------------------------------------------------------------------- /nextjs/.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | node_modules/ 3 | .next/ 4 | .env -------------------------------------------------------------------------------- /nextjs/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_NEST_HOST=http://localhost:3000 -------------------------------------------------------------------------------- /nextjs/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /nextjs/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | 39 | 40 | .env 41 | .history/ -------------------------------------------------------------------------------- /nextjs/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.colorCustomizations": { 3 | "activityBar.activeBackground": "#93e6fc", 4 | "activityBar.activeBorder": "#fa45d4", 5 | "activityBar.background": "#93e6fc", 6 | "activityBar.foreground": "#15202b", 7 | "activityBar.inactiveForeground": "#15202b99", 8 | "activityBarBadge.background": "#fa45d4", 9 | "activityBarBadge.foreground": "#15202b", 10 | "sash.hoverBorder": "#93e6fc", 11 | "statusBar.background": "#93e6fc", 12 | "statusBar.foreground": "#15202b", 13 | "statusBarItem.hoverBackground": "#61dbfb", 14 | "statusBarItem.remoteBackground": "#93e6fc", 15 | "statusBarItem.remoteForeground": "#15202b", 16 | "tab.activeBorder": "#93e6fc", 17 | "titleBar.activeBackground": "#93e6fc", 18 | "titleBar.activeForeground": "#15202b", 19 | "titleBar.inactiveBackground": "#93e6fc99", 20 | "titleBar.inactiveForeground": "#15202b99" 21 | }, 22 | "peacock.remoteColor": "#61dafb" 23 | } -------------------------------------------------------------------------------- /nextjs/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14.15.4-alpine3.12 2 | 3 | USER node 4 | 5 | WORKDIR /home/node/app -------------------------------------------------------------------------------- /nextjs/Dockerfile.prod: -------------------------------------------------------------------------------- 1 | FROM node:14.15.4-slim 2 | 3 | WORKDIR /app 4 | 5 | COPY package*.json ./ 6 | 7 | RUN npm install 8 | 9 | COPY . . 10 | 11 | RUN npm run build 12 | 13 | EXPOSE 3000 14 | 15 | CMD [ "npm", "start" ] -------------------------------------------------------------------------------- /nextjs/README.md: -------------------------------------------------------------------------------- 1 |  2 | 3 | # Imersão Full Stack & FullCycle 5.0 - Front-end do monitoramento de tweets 4 | 5 | ## Descrição 6 | 7 | Repositório do front-end do monitoramento de tweets feito com Next.js 8 | 9 | **Importante**: A aplicação do Apache Kafka e Nest.js deve estar rodando primeiro. 10 | 11 | ### Configurar /etc/hosts 12 | 13 | A comunicação entre as aplicações se dá de forma direta através da rede da máquina. 14 | Para isto é necessário configurar um endereços que todos os containers Docker consigam acessar. 15 | 16 | Acrescente no seu /etc/hosts (para Windows o caminho é C:\Windows\system32\drivers\etc\hosts): 17 | ``` 18 | 127.0.0.1 host.docker.internal 19 | ``` 20 | Em todos os sistemas operacionais é necessário abrir o programa para editar o *hosts* como Administrator da máquina ou root. 21 | 22 | Execute os comando: 23 | 24 | ``` 25 | docker-compose up 26 | ``` 27 | 28 | Acessar http://localhost:3001. 29 | 30 | ### Para Windows 31 | 32 | Quer configurar um ambiente de desenvolvimento produtivo? Veja o vídeo: [https://www.youtube.com/watch?v=bniD6dehPCQ](https://www.youtube.com/watch?v=bniD6dehPCQ) 33 | 34 | ### Para Windows 35 | 36 | Siga o guia rápido de instalação: [https://github.com/codeedu/wsl2-docker-quickstart](https://github.com/codeedu/wsl2-docker-quickstart) 37 | -------------------------------------------------------------------------------- /nextjs/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | app: 5 | build: . 6 | entrypoint: .docker/entrypoint.sh 7 | volumes: 8 | - .:/home/node/app 9 | ports: 10 | - 3001:3000 -------------------------------------------------------------------------------- /nextjs/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /nextjs/next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | images: { 5 | domains: ['localhost', 'pbs.twimg.com', 'abs.twimg.com'] 6 | } 7 | } 8 | 9 | module.exports = nextConfig 10 | -------------------------------------------------------------------------------- /nextjs/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs", 3 | "requires": true, 4 | "lockfileVersion": 1, 5 | "dependencies": { 6 | "@babel/code-frame": { 7 | "version": "7.16.7", 8 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", 9 | "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", 10 | "requires": { 11 | "@babel/highlight": "^7.16.7" 12 | } 13 | }, 14 | "@babel/helper-validator-identifier": { 15 | "version": "7.16.7", 16 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", 17 | "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" 18 | }, 19 | "@babel/highlight": { 20 | "version": "7.16.10", 21 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", 22 | "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", 23 | "requires": { 24 | "@babel/helper-validator-identifier": "^7.16.7", 25 | "chalk": "^2.0.0", 26 | "js-tokens": "^4.0.0" 27 | }, 28 | "dependencies": { 29 | "ansi-styles": { 30 | "version": "3.2.1", 31 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 32 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 33 | "requires": { 34 | "color-convert": "^1.9.0" 35 | } 36 | }, 37 | "chalk": { 38 | "version": "2.4.2", 39 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 40 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 41 | "requires": { 42 | "ansi-styles": "^3.2.1", 43 | "escape-string-regexp": "^1.0.5", 44 | "supports-color": "^5.3.0" 45 | } 46 | }, 47 | "color-convert": { 48 | "version": "1.9.3", 49 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 50 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 51 | "requires": { 52 | "color-name": "1.1.3" 53 | } 54 | }, 55 | "color-name": { 56 | "version": "1.1.3", 57 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 58 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 59 | }, 60 | "escape-string-regexp": { 61 | "version": "1.0.5", 62 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 63 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 64 | }, 65 | "has-flag": { 66 | "version": "3.0.0", 67 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 68 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 69 | }, 70 | "supports-color": { 71 | "version": "5.5.0", 72 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 73 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 74 | "requires": { 75 | "has-flag": "^3.0.0" 76 | } 77 | } 78 | } 79 | }, 80 | "@babel/runtime": { 81 | "version": "7.17.0", 82 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.0.tgz", 83 | "integrity": "sha512-etcO/ohMNaNA2UBdaXBBSX/3aEzFMRrVfaPv8Ptc0k+cWpWW0QFiGZ2XnVqQZI1Cf734LbPGmqBKWESfW4x/dQ==", 84 | "dev": true, 85 | "requires": { 86 | "regenerator-runtime": "^0.13.4" 87 | } 88 | }, 89 | "@babel/runtime-corejs3": { 90 | "version": "7.17.0", 91 | "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.17.0.tgz", 92 | "integrity": "sha512-qeydncU80ravKzovVncW3EYaC1ji3GpntdPgNcJy9g7hHSY6KX+ne1cbV3ov7Zzm4F1z0+QreZPCuw1ynkmYNg==", 93 | "dev": true, 94 | "requires": { 95 | "core-js-pure": "^3.20.2", 96 | "regenerator-runtime": "^0.13.4" 97 | } 98 | }, 99 | "@eslint/eslintrc": { 100 | "version": "1.0.5", 101 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz", 102 | "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==", 103 | "dev": true, 104 | "requires": { 105 | "ajv": "^6.12.4", 106 | "debug": "^4.3.2", 107 | "espree": "^9.2.0", 108 | "globals": "^13.9.0", 109 | "ignore": "^4.0.6", 110 | "import-fresh": "^3.2.1", 111 | "js-yaml": "^4.1.0", 112 | "minimatch": "^3.0.4", 113 | "strip-json-comments": "^3.1.1" 114 | }, 115 | "dependencies": { 116 | "ignore": { 117 | "version": "4.0.6", 118 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 119 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 120 | "dev": true 121 | } 122 | } 123 | }, 124 | "@fortawesome/fontawesome-free": { 125 | "version": "5.15.4", 126 | "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz", 127 | "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==" 128 | }, 129 | "@humanwhocodes/config-array": { 130 | "version": "0.9.3", 131 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", 132 | "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", 133 | "dev": true, 134 | "requires": { 135 | "@humanwhocodes/object-schema": "^1.2.1", 136 | "debug": "^4.1.1", 137 | "minimatch": "^3.0.4" 138 | } 139 | }, 140 | "@humanwhocodes/object-schema": { 141 | "version": "1.2.1", 142 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 143 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 144 | "dev": true 145 | }, 146 | "@next/env": { 147 | "version": "12.0.10", 148 | "resolved": "https://registry.npmjs.org/@next/env/-/env-12.0.10.tgz", 149 | "integrity": "sha512-mQVj0K6wQ5WEk/sL9SZ+mJXJUaG7el8CpZ6io1uFe9GgNTSC7EgUyNGqM6IQovIFc5ukF4O/hqsdh3S/DCgT2g==" 150 | }, 151 | "@next/eslint-plugin-next": { 152 | "version": "12.0.10", 153 | "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.0.10.tgz", 154 | "integrity": "sha512-PbGRnV5HGSfRGLjf8uTh1MaWgLwnjKjWiGVjK752ifITJbZ28/5AmLAFT2shDYeux8BHgpgVll5QXu7GN3YLFw==", 155 | "dev": true, 156 | "requires": { 157 | "glob": "7.1.7" 158 | }, 159 | "dependencies": { 160 | "glob": { 161 | "version": "7.1.7", 162 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 163 | "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 164 | "dev": true, 165 | "requires": { 166 | "fs.realpath": "^1.0.0", 167 | "inflight": "^1.0.4", 168 | "inherits": "2", 169 | "minimatch": "^3.0.4", 170 | "once": "^1.3.0", 171 | "path-is-absolute": "^1.0.0" 172 | } 173 | } 174 | } 175 | }, 176 | "@next/swc-android-arm64": { 177 | "version": "12.0.10", 178 | "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.0.10.tgz", 179 | "integrity": "sha512-xYwXGkNhzZZsM5MD7KRwF5ZNiC8OLPtVMUiagpPnwENg8Hb0GSQo/NbYWXM8YrawEwp9LaZ7OXiuRKPh2JyBdA==", 180 | "optional": true 181 | }, 182 | "@next/swc-darwin-arm64": { 183 | "version": "12.0.10", 184 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.10.tgz", 185 | "integrity": "sha512-f2zngulkpIJKWHckhRi7X8GZ+J/tNgFF7lYIh7Qx15JH0OTBsjkqxORlkzy+VZyHJ5sWTCaI6HYYd3ow6qkEEg==", 186 | "optional": true 187 | }, 188 | "@next/swc-darwin-x64": { 189 | "version": "12.0.10", 190 | "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.10.tgz", 191 | "integrity": "sha512-Qykcu/gVC5oTvOQoRBhyuS5GYm5SbcgrFTsaLFkGBmEkg9eMQRiaCswk4IafpDXVzITkVFurzSM28q3tLW2qUw==", 192 | "optional": true 193 | }, 194 | "@next/swc-linux-arm-gnueabihf": { 195 | "version": "12.0.10", 196 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.10.tgz", 197 | "integrity": "sha512-EhqrTFsIXAXN9B/fiiW/QKUK/lSLCXRsLalkUp58KDfMqVLLlj1ORbESAcswiNQOChLuHQSldGEEtOBPQZcd9A==", 198 | "optional": true 199 | }, 200 | "@next/swc-linux-arm64-gnu": { 201 | "version": "12.0.10", 202 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.10.tgz", 203 | "integrity": "sha512-kqGtC72g3+JYXZbY2ca6digXR5U6AQ6Dzv4eAxYluMePLHjI/Xye1mf9dwVsgmeXfrD/IRDp5K/3A6UNvBm4oQ==", 204 | "optional": true 205 | }, 206 | "@next/swc-linux-arm64-musl": { 207 | "version": "12.0.10", 208 | "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.10.tgz", 209 | "integrity": "sha512-bG9zTSNwnSgc1Un/7oz1ZVN4UeXsTWrsQhAGWU78lLLCn4Zj9HQoUCRCGLt0OVs2DBZ+WC8CzzFliQ1SKipVbg==", 210 | "optional": true 211 | }, 212 | "@next/swc-linux-x64-gnu": { 213 | "version": "12.0.10", 214 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.10.tgz", 215 | "integrity": "sha512-c79PcfWtyThiYRa1+3KVfDq0zXaI8o1d6dQWNVqDrtLz5HKM/rbjLdvoNuxDwUeZhxI/d9CtyH6GbuKPw5l/5A==", 216 | "optional": true 217 | }, 218 | "@next/swc-linux-x64-musl": { 219 | "version": "12.0.10", 220 | "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.10.tgz", 221 | "integrity": "sha512-g/scgn+21/MLfizOCZOZt+MxNj2/8Tdlwjvy+QZcSUPZRUI2Y5o3HwBvI1f/bSci+NGRU+bUAO0NFtRJ9MzH5w==", 222 | "optional": true 223 | }, 224 | "@next/swc-win32-arm64-msvc": { 225 | "version": "12.0.10", 226 | "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.10.tgz", 227 | "integrity": "sha512-gl6B/ravwMeY5Nv4Il2/ARYJQ6u+KPRwGMjS1ZrNudIKlNn4YBeXh5A4cIVm+dHaff6/O/lGOa5/SUYDMZpkww==", 228 | "optional": true 229 | }, 230 | "@next/swc-win32-ia32-msvc": { 231 | "version": "12.0.10", 232 | "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.10.tgz", 233 | "integrity": "sha512-7RVpZ3tSThC6j+iZB0CUYmFiA3kXmN+pE7QcfyAxFaflKlaZoWNMKHIEZDuxSJc6YmQ6kyxsjqxVay2F5+/YCg==", 234 | "optional": true 235 | }, 236 | "@next/swc-win32-x64-msvc": { 237 | "version": "12.0.10", 238 | "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.10.tgz", 239 | "integrity": "sha512-oUIWRKd24jFLRWUYO1CZmML5+32BcpVfqhimGaaZIXcOkfQW+iqiAzdqsv688zaGtyKGeB9ZtiK3NDf+Q0v+Vw==", 240 | "optional": true 241 | }, 242 | "@nodelib/fs.scandir": { 243 | "version": "2.1.5", 244 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 245 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 246 | "requires": { 247 | "@nodelib/fs.stat": "2.0.5", 248 | "run-parallel": "^1.1.9" 249 | } 250 | }, 251 | "@nodelib/fs.stat": { 252 | "version": "2.0.5", 253 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 254 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" 255 | }, 256 | "@nodelib/fs.walk": { 257 | "version": "1.2.8", 258 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 259 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 260 | "requires": { 261 | "@nodelib/fs.scandir": "2.1.5", 262 | "fastq": "^1.6.0" 263 | } 264 | }, 265 | "@rushstack/eslint-patch": { 266 | "version": "1.1.0", 267 | "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz", 268 | "integrity": "sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==", 269 | "dev": true 270 | }, 271 | "@types/json5": { 272 | "version": "0.0.29", 273 | "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", 274 | "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", 275 | "dev": true 276 | }, 277 | "@types/node": { 278 | "version": "17.0.15", 279 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.15.tgz", 280 | "integrity": "sha512-zWt4SDDv1S9WRBNxLFxFRHxdD9tvH8f5/kg5/IaLFdnSNXsDY4eL3Q3XXN+VxUnWIhyVFDwcsmAprvwXoM/ClA==", 281 | "dev": true 282 | }, 283 | "@types/parse-json": { 284 | "version": "4.0.0", 285 | "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", 286 | "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" 287 | }, 288 | "@types/prop-types": { 289 | "version": "15.7.4", 290 | "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", 291 | "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", 292 | "dev": true 293 | }, 294 | "@types/react": { 295 | "version": "17.0.39", 296 | "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", 297 | "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", 298 | "dev": true, 299 | "requires": { 300 | "@types/prop-types": "*", 301 | "@types/scheduler": "*", 302 | "csstype": "^3.0.2" 303 | } 304 | }, 305 | "@types/scheduler": { 306 | "version": "0.16.2", 307 | "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", 308 | "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", 309 | "dev": true 310 | }, 311 | "@typescript-eslint/parser": { 312 | "version": "5.10.2", 313 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.10.2.tgz", 314 | "integrity": "sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg==", 315 | "dev": true, 316 | "requires": { 317 | "@typescript-eslint/scope-manager": "5.10.2", 318 | "@typescript-eslint/types": "5.10.2", 319 | "@typescript-eslint/typescript-estree": "5.10.2", 320 | "debug": "^4.3.2" 321 | } 322 | }, 323 | "@typescript-eslint/scope-manager": { 324 | "version": "5.10.2", 325 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.10.2.tgz", 326 | "integrity": "sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw==", 327 | "dev": true, 328 | "requires": { 329 | "@typescript-eslint/types": "5.10.2", 330 | "@typescript-eslint/visitor-keys": "5.10.2" 331 | } 332 | }, 333 | "@typescript-eslint/types": { 334 | "version": "5.10.2", 335 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.10.2.tgz", 336 | "integrity": "sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w==", 337 | "dev": true 338 | }, 339 | "@typescript-eslint/typescript-estree": { 340 | "version": "5.10.2", 341 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz", 342 | "integrity": "sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==", 343 | "dev": true, 344 | "requires": { 345 | "@typescript-eslint/types": "5.10.2", 346 | "@typescript-eslint/visitor-keys": "5.10.2", 347 | "debug": "^4.3.2", 348 | "globby": "^11.0.4", 349 | "is-glob": "^4.0.3", 350 | "semver": "^7.3.5", 351 | "tsutils": "^3.21.0" 352 | } 353 | }, 354 | "@typescript-eslint/visitor-keys": { 355 | "version": "5.10.2", 356 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.2.tgz", 357 | "integrity": "sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q==", 358 | "dev": true, 359 | "requires": { 360 | "@typescript-eslint/types": "5.10.2", 361 | "eslint-visitor-keys": "^3.0.0" 362 | } 363 | }, 364 | "acorn": { 365 | "version": "8.7.0", 366 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", 367 | "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", 368 | "dev": true 369 | }, 370 | "acorn-jsx": { 371 | "version": "5.3.2", 372 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 373 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 374 | "dev": true 375 | }, 376 | "acorn-node": { 377 | "version": "1.8.2", 378 | "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", 379 | "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", 380 | "requires": { 381 | "acorn": "^7.0.0", 382 | "acorn-walk": "^7.0.0", 383 | "xtend": "^4.0.2" 384 | }, 385 | "dependencies": { 386 | "acorn": { 387 | "version": "7.4.1", 388 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 389 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" 390 | } 391 | } 392 | }, 393 | "acorn-walk": { 394 | "version": "7.2.0", 395 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", 396 | "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" 397 | }, 398 | "ajv": { 399 | "version": "6.12.6", 400 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 401 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 402 | "dev": true, 403 | "requires": { 404 | "fast-deep-equal": "^3.1.1", 405 | "fast-json-stable-stringify": "^2.0.0", 406 | "json-schema-traverse": "^0.4.1", 407 | "uri-js": "^4.2.2" 408 | } 409 | }, 410 | "ansi-regex": { 411 | "version": "5.0.1", 412 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 413 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 414 | "dev": true 415 | }, 416 | "ansi-styles": { 417 | "version": "4.3.0", 418 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 419 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 420 | "requires": { 421 | "color-convert": "^2.0.1" 422 | } 423 | }, 424 | "anymatch": { 425 | "version": "3.1.2", 426 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 427 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 428 | "requires": { 429 | "normalize-path": "^3.0.0", 430 | "picomatch": "^2.0.4" 431 | } 432 | }, 433 | "arg": { 434 | "version": "5.0.1", 435 | "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", 436 | "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==" 437 | }, 438 | "argparse": { 439 | "version": "2.0.1", 440 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 441 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 442 | "dev": true 443 | }, 444 | "aria-query": { 445 | "version": "4.2.2", 446 | "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", 447 | "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", 448 | "dev": true, 449 | "requires": { 450 | "@babel/runtime": "^7.10.2", 451 | "@babel/runtime-corejs3": "^7.10.2" 452 | } 453 | }, 454 | "array-includes": { 455 | "version": "3.1.4", 456 | "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", 457 | "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", 458 | "dev": true, 459 | "requires": { 460 | "call-bind": "^1.0.2", 461 | "define-properties": "^1.1.3", 462 | "es-abstract": "^1.19.1", 463 | "get-intrinsic": "^1.1.1", 464 | "is-string": "^1.0.7" 465 | } 466 | }, 467 | "array-union": { 468 | "version": "2.1.0", 469 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 470 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 471 | "dev": true 472 | }, 473 | "array.prototype.flat": { 474 | "version": "1.2.5", 475 | "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", 476 | "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", 477 | "dev": true, 478 | "requires": { 479 | "call-bind": "^1.0.2", 480 | "define-properties": "^1.1.3", 481 | "es-abstract": "^1.19.0" 482 | } 483 | }, 484 | "array.prototype.flatmap": { 485 | "version": "1.2.5", 486 | "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz", 487 | "integrity": "sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==", 488 | "dev": true, 489 | "requires": { 490 | "call-bind": "^1.0.0", 491 | "define-properties": "^1.1.3", 492 | "es-abstract": "^1.19.0" 493 | } 494 | }, 495 | "ast-types-flow": { 496 | "version": "0.0.7", 497 | "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", 498 | "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", 499 | "dev": true 500 | }, 501 | "autoprefixer": { 502 | "version": "10.4.2", 503 | "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", 504 | "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", 505 | "requires": { 506 | "browserslist": "^4.19.1", 507 | "caniuse-lite": "^1.0.30001297", 508 | "fraction.js": "^4.1.2", 509 | "normalize-range": "^0.1.2", 510 | "picocolors": "^1.0.0", 511 | "postcss-value-parser": "^4.2.0" 512 | } 513 | }, 514 | "axe-core": { 515 | "version": "4.4.1", 516 | "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", 517 | "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", 518 | "dev": true 519 | }, 520 | "axios": { 521 | "version": "0.25.0", 522 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz", 523 | "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==", 524 | "requires": { 525 | "follow-redirects": "^1.14.7" 526 | } 527 | }, 528 | "axobject-query": { 529 | "version": "2.2.0", 530 | "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", 531 | "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", 532 | "dev": true 533 | }, 534 | "balanced-match": { 535 | "version": "1.0.2", 536 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 537 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 538 | "dev": true 539 | }, 540 | "binary-extensions": { 541 | "version": "2.2.0", 542 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 543 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" 544 | }, 545 | "brace-expansion": { 546 | "version": "1.1.11", 547 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 548 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 549 | "dev": true, 550 | "requires": { 551 | "balanced-match": "^1.0.0", 552 | "concat-map": "0.0.1" 553 | } 554 | }, 555 | "braces": { 556 | "version": "3.0.2", 557 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 558 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 559 | "requires": { 560 | "fill-range": "^7.0.1" 561 | } 562 | }, 563 | "browserslist": { 564 | "version": "4.19.1", 565 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", 566 | "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", 567 | "requires": { 568 | "caniuse-lite": "^1.0.30001286", 569 | "electron-to-chromium": "^1.4.17", 570 | "escalade": "^3.1.1", 571 | "node-releases": "^2.0.1", 572 | "picocolors": "^1.0.0" 573 | } 574 | }, 575 | "call-bind": { 576 | "version": "1.0.2", 577 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 578 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 579 | "dev": true, 580 | "requires": { 581 | "function-bind": "^1.1.1", 582 | "get-intrinsic": "^1.0.2" 583 | } 584 | }, 585 | "callsites": { 586 | "version": "3.1.0", 587 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 588 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" 589 | }, 590 | "camelcase-css": { 591 | "version": "2.0.1", 592 | "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", 593 | "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" 594 | }, 595 | "caniuse-lite": { 596 | "version": "1.0.30001307", 597 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001307.tgz", 598 | "integrity": "sha512-+MXEMczJ4FuxJAUp0jvAl6Df0NI/OfW1RWEE61eSmzS7hw6lz4IKutbhbXendwq8BljfFuHtu26VWsg4afQ7Ng==" 599 | }, 600 | "chalk": { 601 | "version": "4.1.2", 602 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 603 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 604 | "requires": { 605 | "ansi-styles": "^4.1.0", 606 | "supports-color": "^7.1.0" 607 | } 608 | }, 609 | "chokidar": { 610 | "version": "3.5.3", 611 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 612 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 613 | "requires": { 614 | "anymatch": "~3.1.2", 615 | "braces": "~3.0.2", 616 | "fsevents": "~2.3.2", 617 | "glob-parent": "~5.1.2", 618 | "is-binary-path": "~2.1.0", 619 | "is-glob": "~4.0.1", 620 | "normalize-path": "~3.0.0", 621 | "readdirp": "~3.6.0" 622 | }, 623 | "dependencies": { 624 | "glob-parent": { 625 | "version": "5.1.2", 626 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 627 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 628 | "requires": { 629 | "is-glob": "^4.0.1" 630 | } 631 | } 632 | } 633 | }, 634 | "color-convert": { 635 | "version": "2.0.1", 636 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 637 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 638 | "requires": { 639 | "color-name": "~1.1.4" 640 | } 641 | }, 642 | "color-name": { 643 | "version": "1.1.4", 644 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 645 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 646 | }, 647 | "concat-map": { 648 | "version": "0.0.1", 649 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 650 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 651 | "dev": true 652 | }, 653 | "core-js-pure": { 654 | "version": "3.21.0", 655 | "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.0.tgz", 656 | "integrity": "sha512-VaJUunCZLnxuDbo1rNOzwbet9E1K9joiXS5+DQMPtgxd24wfsZbJZMMfQLGYMlCUvSxLfsRUUhoOR2x28mFfeg==", 657 | "dev": true 658 | }, 659 | "cosmiconfig": { 660 | "version": "7.0.1", 661 | "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", 662 | "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", 663 | "requires": { 664 | "@types/parse-json": "^4.0.0", 665 | "import-fresh": "^3.2.1", 666 | "parse-json": "^5.0.0", 667 | "path-type": "^4.0.0", 668 | "yaml": "^1.10.0" 669 | } 670 | }, 671 | "cross-spawn": { 672 | "version": "7.0.3", 673 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 674 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 675 | "dev": true, 676 | "requires": { 677 | "path-key": "^3.1.0", 678 | "shebang-command": "^2.0.0", 679 | "which": "^2.0.1" 680 | } 681 | }, 682 | "cssesc": { 683 | "version": "3.0.0", 684 | "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", 685 | "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" 686 | }, 687 | "csstype": { 688 | "version": "3.0.10", 689 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", 690 | "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", 691 | "dev": true 692 | }, 693 | "damerau-levenshtein": { 694 | "version": "1.0.8", 695 | "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", 696 | "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", 697 | "dev": true 698 | }, 699 | "debug": { 700 | "version": "4.3.3", 701 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 702 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 703 | "dev": true, 704 | "requires": { 705 | "ms": "2.1.2" 706 | } 707 | }, 708 | "deep-is": { 709 | "version": "0.1.4", 710 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 711 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 712 | "dev": true 713 | }, 714 | "define-properties": { 715 | "version": "1.1.3", 716 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 717 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 718 | "dev": true, 719 | "requires": { 720 | "object-keys": "^1.0.12" 721 | } 722 | }, 723 | "defined": { 724 | "version": "1.0.0", 725 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", 726 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" 727 | }, 728 | "detective": { 729 | "version": "5.2.0", 730 | "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", 731 | "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", 732 | "requires": { 733 | "acorn-node": "^1.6.1", 734 | "defined": "^1.0.0", 735 | "minimist": "^1.1.1" 736 | } 737 | }, 738 | "didyoumean": { 739 | "version": "1.2.2", 740 | "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", 741 | "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" 742 | }, 743 | "dir-glob": { 744 | "version": "3.0.1", 745 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 746 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 747 | "dev": true, 748 | "requires": { 749 | "path-type": "^4.0.0" 750 | } 751 | }, 752 | "dlv": { 753 | "version": "1.1.3", 754 | "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", 755 | "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" 756 | }, 757 | "doctrine": { 758 | "version": "3.0.0", 759 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 760 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 761 | "dev": true, 762 | "requires": { 763 | "esutils": "^2.0.2" 764 | } 765 | }, 766 | "electron-to-chromium": { 767 | "version": "1.4.65", 768 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.65.tgz", 769 | "integrity": "sha512-0/d8Skk8sW3FxXP0Dd6MnBlrwx7Qo9cqQec3BlIAlvKnrmS3pHsIbaroEi+nd0kZkGpQ6apMEre7xndzjlEnLw==" 770 | }, 771 | "emoji-regex": { 772 | "version": "9.2.2", 773 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 774 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 775 | "dev": true 776 | }, 777 | "error-ex": { 778 | "version": "1.3.2", 779 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 780 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 781 | "requires": { 782 | "is-arrayish": "^0.2.1" 783 | } 784 | }, 785 | "es-abstract": { 786 | "version": "1.19.1", 787 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", 788 | "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", 789 | "dev": true, 790 | "requires": { 791 | "call-bind": "^1.0.2", 792 | "es-to-primitive": "^1.2.1", 793 | "function-bind": "^1.1.1", 794 | "get-intrinsic": "^1.1.1", 795 | "get-symbol-description": "^1.0.0", 796 | "has": "^1.0.3", 797 | "has-symbols": "^1.0.2", 798 | "internal-slot": "^1.0.3", 799 | "is-callable": "^1.2.4", 800 | "is-negative-zero": "^2.0.1", 801 | "is-regex": "^1.1.4", 802 | "is-shared-array-buffer": "^1.0.1", 803 | "is-string": "^1.0.7", 804 | "is-weakref": "^1.0.1", 805 | "object-inspect": "^1.11.0", 806 | "object-keys": "^1.1.1", 807 | "object.assign": "^4.1.2", 808 | "string.prototype.trimend": "^1.0.4", 809 | "string.prototype.trimstart": "^1.0.4", 810 | "unbox-primitive": "^1.0.1" 811 | } 812 | }, 813 | "es-to-primitive": { 814 | "version": "1.2.1", 815 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 816 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 817 | "dev": true, 818 | "requires": { 819 | "is-callable": "^1.1.4", 820 | "is-date-object": "^1.0.1", 821 | "is-symbol": "^1.0.2" 822 | } 823 | }, 824 | "escalade": { 825 | "version": "3.1.1", 826 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 827 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" 828 | }, 829 | "escape-string-regexp": { 830 | "version": "4.0.0", 831 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 832 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 833 | "dev": true 834 | }, 835 | "eslint": { 836 | "version": "8.8.0", 837 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.8.0.tgz", 838 | "integrity": "sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==", 839 | "dev": true, 840 | "requires": { 841 | "@eslint/eslintrc": "^1.0.5", 842 | "@humanwhocodes/config-array": "^0.9.2", 843 | "ajv": "^6.10.0", 844 | "chalk": "^4.0.0", 845 | "cross-spawn": "^7.0.2", 846 | "debug": "^4.3.2", 847 | "doctrine": "^3.0.0", 848 | "escape-string-regexp": "^4.0.0", 849 | "eslint-scope": "^7.1.0", 850 | "eslint-utils": "^3.0.0", 851 | "eslint-visitor-keys": "^3.2.0", 852 | "espree": "^9.3.0", 853 | "esquery": "^1.4.0", 854 | "esutils": "^2.0.2", 855 | "fast-deep-equal": "^3.1.3", 856 | "file-entry-cache": "^6.0.1", 857 | "functional-red-black-tree": "^1.0.1", 858 | "glob-parent": "^6.0.1", 859 | "globals": "^13.6.0", 860 | "ignore": "^5.2.0", 861 | "import-fresh": "^3.0.0", 862 | "imurmurhash": "^0.1.4", 863 | "is-glob": "^4.0.0", 864 | "js-yaml": "^4.1.0", 865 | "json-stable-stringify-without-jsonify": "^1.0.1", 866 | "levn": "^0.4.1", 867 | "lodash.merge": "^4.6.2", 868 | "minimatch": "^3.0.4", 869 | "natural-compare": "^1.4.0", 870 | "optionator": "^0.9.1", 871 | "regexpp": "^3.2.0", 872 | "strip-ansi": "^6.0.1", 873 | "strip-json-comments": "^3.1.0", 874 | "text-table": "^0.2.0", 875 | "v8-compile-cache": "^2.0.3" 876 | } 877 | }, 878 | "eslint-config-next": { 879 | "version": "12.0.10", 880 | "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-12.0.10.tgz", 881 | "integrity": "sha512-l1er6mwSo1bltjLwmd71p5BdT6k/NQxV1n4lKZI6xt3MDMrq7ChUBr+EecxOry8GC/rCRUtPpH8Ygs0BJc5YLg==", 882 | "dev": true, 883 | "requires": { 884 | "@next/eslint-plugin-next": "12.0.10", 885 | "@rushstack/eslint-patch": "^1.0.8", 886 | "@typescript-eslint/parser": "^5.0.0", 887 | "eslint-import-resolver-node": "^0.3.4", 888 | "eslint-import-resolver-typescript": "^2.4.0", 889 | "eslint-plugin-import": "^2.25.2", 890 | "eslint-plugin-jsx-a11y": "^6.5.1", 891 | "eslint-plugin-react": "^7.27.0", 892 | "eslint-plugin-react-hooks": "^4.3.0" 893 | } 894 | }, 895 | "eslint-import-resolver-node": { 896 | "version": "0.3.6", 897 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", 898 | "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", 899 | "dev": true, 900 | "requires": { 901 | "debug": "^3.2.7", 902 | "resolve": "^1.20.0" 903 | }, 904 | "dependencies": { 905 | "debug": { 906 | "version": "3.2.7", 907 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 908 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 909 | "dev": true, 910 | "requires": { 911 | "ms": "^2.1.1" 912 | } 913 | } 914 | } 915 | }, 916 | "eslint-import-resolver-typescript": { 917 | "version": "2.5.0", 918 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz", 919 | "integrity": "sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==", 920 | "dev": true, 921 | "requires": { 922 | "debug": "^4.3.1", 923 | "glob": "^7.1.7", 924 | "is-glob": "^4.0.1", 925 | "resolve": "^1.20.0", 926 | "tsconfig-paths": "^3.9.0" 927 | } 928 | }, 929 | "eslint-module-utils": { 930 | "version": "2.7.3", 931 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", 932 | "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", 933 | "dev": true, 934 | "requires": { 935 | "debug": "^3.2.7", 936 | "find-up": "^2.1.0" 937 | }, 938 | "dependencies": { 939 | "debug": { 940 | "version": "3.2.7", 941 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 942 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 943 | "dev": true, 944 | "requires": { 945 | "ms": "^2.1.1" 946 | } 947 | } 948 | } 949 | }, 950 | "eslint-plugin-import": { 951 | "version": "2.25.4", 952 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", 953 | "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", 954 | "dev": true, 955 | "requires": { 956 | "array-includes": "^3.1.4", 957 | "array.prototype.flat": "^1.2.5", 958 | "debug": "^2.6.9", 959 | "doctrine": "^2.1.0", 960 | "eslint-import-resolver-node": "^0.3.6", 961 | "eslint-module-utils": "^2.7.2", 962 | "has": "^1.0.3", 963 | "is-core-module": "^2.8.0", 964 | "is-glob": "^4.0.3", 965 | "minimatch": "^3.0.4", 966 | "object.values": "^1.1.5", 967 | "resolve": "^1.20.0", 968 | "tsconfig-paths": "^3.12.0" 969 | }, 970 | "dependencies": { 971 | "debug": { 972 | "version": "2.6.9", 973 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 974 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 975 | "dev": true, 976 | "requires": { 977 | "ms": "2.0.0" 978 | } 979 | }, 980 | "doctrine": { 981 | "version": "2.1.0", 982 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 983 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 984 | "dev": true, 985 | "requires": { 986 | "esutils": "^2.0.2" 987 | } 988 | }, 989 | "ms": { 990 | "version": "2.0.0", 991 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 992 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 993 | "dev": true 994 | } 995 | } 996 | }, 997 | "eslint-plugin-jsx-a11y": { 998 | "version": "6.5.1", 999 | "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", 1000 | "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", 1001 | "dev": true, 1002 | "requires": { 1003 | "@babel/runtime": "^7.16.3", 1004 | "aria-query": "^4.2.2", 1005 | "array-includes": "^3.1.4", 1006 | "ast-types-flow": "^0.0.7", 1007 | "axe-core": "^4.3.5", 1008 | "axobject-query": "^2.2.0", 1009 | "damerau-levenshtein": "^1.0.7", 1010 | "emoji-regex": "^9.2.2", 1011 | "has": "^1.0.3", 1012 | "jsx-ast-utils": "^3.2.1", 1013 | "language-tags": "^1.0.5", 1014 | "minimatch": "^3.0.4" 1015 | } 1016 | }, 1017 | "eslint-plugin-react": { 1018 | "version": "7.28.0", 1019 | "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.28.0.tgz", 1020 | "integrity": "sha512-IOlFIRHzWfEQQKcAD4iyYDndHwTQiCMcJVJjxempf203jnNLUnW34AXLrV33+nEXoifJE2ZEGmcjKPL8957eSw==", 1021 | "dev": true, 1022 | "requires": { 1023 | "array-includes": "^3.1.4", 1024 | "array.prototype.flatmap": "^1.2.5", 1025 | "doctrine": "^2.1.0", 1026 | "estraverse": "^5.3.0", 1027 | "jsx-ast-utils": "^2.4.1 || ^3.0.0", 1028 | "minimatch": "^3.0.4", 1029 | "object.entries": "^1.1.5", 1030 | "object.fromentries": "^2.0.5", 1031 | "object.hasown": "^1.1.0", 1032 | "object.values": "^1.1.5", 1033 | "prop-types": "^15.7.2", 1034 | "resolve": "^2.0.0-next.3", 1035 | "semver": "^6.3.0", 1036 | "string.prototype.matchall": "^4.0.6" 1037 | }, 1038 | "dependencies": { 1039 | "doctrine": { 1040 | "version": "2.1.0", 1041 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 1042 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 1043 | "dev": true, 1044 | "requires": { 1045 | "esutils": "^2.0.2" 1046 | } 1047 | }, 1048 | "resolve": { 1049 | "version": "2.0.0-next.3", 1050 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz", 1051 | "integrity": "sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==", 1052 | "dev": true, 1053 | "requires": { 1054 | "is-core-module": "^2.2.0", 1055 | "path-parse": "^1.0.6" 1056 | } 1057 | }, 1058 | "semver": { 1059 | "version": "6.3.0", 1060 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1061 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1062 | "dev": true 1063 | } 1064 | } 1065 | }, 1066 | "eslint-plugin-react-hooks": { 1067 | "version": "4.3.0", 1068 | "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz", 1069 | "integrity": "sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==", 1070 | "dev": true 1071 | }, 1072 | "eslint-scope": { 1073 | "version": "7.1.0", 1074 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.0.tgz", 1075 | "integrity": "sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==", 1076 | "dev": true, 1077 | "requires": { 1078 | "esrecurse": "^4.3.0", 1079 | "estraverse": "^5.2.0" 1080 | } 1081 | }, 1082 | "eslint-utils": { 1083 | "version": "3.0.0", 1084 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", 1085 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 1086 | "dev": true, 1087 | "requires": { 1088 | "eslint-visitor-keys": "^2.0.0" 1089 | }, 1090 | "dependencies": { 1091 | "eslint-visitor-keys": { 1092 | "version": "2.1.0", 1093 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 1094 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 1095 | "dev": true 1096 | } 1097 | } 1098 | }, 1099 | "eslint-visitor-keys": { 1100 | "version": "3.2.0", 1101 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz", 1102 | "integrity": "sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==", 1103 | "dev": true 1104 | }, 1105 | "espree": { 1106 | "version": "9.3.0", 1107 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.0.tgz", 1108 | "integrity": "sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==", 1109 | "dev": true, 1110 | "requires": { 1111 | "acorn": "^8.7.0", 1112 | "acorn-jsx": "^5.3.1", 1113 | "eslint-visitor-keys": "^3.1.0" 1114 | } 1115 | }, 1116 | "esquery": { 1117 | "version": "1.4.0", 1118 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 1119 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 1120 | "dev": true, 1121 | "requires": { 1122 | "estraverse": "^5.1.0" 1123 | } 1124 | }, 1125 | "esrecurse": { 1126 | "version": "4.3.0", 1127 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1128 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1129 | "dev": true, 1130 | "requires": { 1131 | "estraverse": "^5.2.0" 1132 | } 1133 | }, 1134 | "estraverse": { 1135 | "version": "5.3.0", 1136 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 1137 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 1138 | "dev": true 1139 | }, 1140 | "esutils": { 1141 | "version": "2.0.3", 1142 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1143 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1144 | "dev": true 1145 | }, 1146 | "fast-deep-equal": { 1147 | "version": "3.1.3", 1148 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1149 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1150 | "dev": true 1151 | }, 1152 | "fast-glob": { 1153 | "version": "3.2.11", 1154 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", 1155 | "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", 1156 | "requires": { 1157 | "@nodelib/fs.stat": "^2.0.2", 1158 | "@nodelib/fs.walk": "^1.2.3", 1159 | "glob-parent": "^5.1.2", 1160 | "merge2": "^1.3.0", 1161 | "micromatch": "^4.0.4" 1162 | }, 1163 | "dependencies": { 1164 | "glob-parent": { 1165 | "version": "5.1.2", 1166 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1167 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1168 | "requires": { 1169 | "is-glob": "^4.0.1" 1170 | } 1171 | } 1172 | } 1173 | }, 1174 | "fast-json-stable-stringify": { 1175 | "version": "2.1.0", 1176 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1177 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1178 | "dev": true 1179 | }, 1180 | "fast-levenshtein": { 1181 | "version": "2.0.6", 1182 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1183 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 1184 | "dev": true 1185 | }, 1186 | "fastq": { 1187 | "version": "1.13.0", 1188 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", 1189 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", 1190 | "requires": { 1191 | "reusify": "^1.0.4" 1192 | } 1193 | }, 1194 | "file-entry-cache": { 1195 | "version": "6.0.1", 1196 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 1197 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 1198 | "dev": true, 1199 | "requires": { 1200 | "flat-cache": "^3.0.4" 1201 | } 1202 | }, 1203 | "fill-range": { 1204 | "version": "7.0.1", 1205 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1206 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1207 | "requires": { 1208 | "to-regex-range": "^5.0.1" 1209 | } 1210 | }, 1211 | "find-up": { 1212 | "version": "2.1.0", 1213 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 1214 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 1215 | "dev": true, 1216 | "requires": { 1217 | "locate-path": "^2.0.0" 1218 | } 1219 | }, 1220 | "flat-cache": { 1221 | "version": "3.0.4", 1222 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 1223 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 1224 | "dev": true, 1225 | "requires": { 1226 | "flatted": "^3.1.0", 1227 | "rimraf": "^3.0.2" 1228 | } 1229 | }, 1230 | "flatted": { 1231 | "version": "3.2.5", 1232 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", 1233 | "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", 1234 | "dev": true 1235 | }, 1236 | "follow-redirects": { 1237 | "version": "1.14.7", 1238 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", 1239 | "integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==" 1240 | }, 1241 | "fraction.js": { 1242 | "version": "4.1.2", 1243 | "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", 1244 | "integrity": "sha512-o2RiJQ6DZaR/5+Si0qJUIy637QMRudSi9kU/FFzx9EZazrIdnBgpU+3sEWCxAVhH2RtxW2Oz+T4p2o8uOPVcgA==" 1245 | }, 1246 | "fs.realpath": { 1247 | "version": "1.0.0", 1248 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1249 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1250 | "dev": true 1251 | }, 1252 | "fsevents": { 1253 | "version": "2.3.2", 1254 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 1255 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 1256 | "optional": true 1257 | }, 1258 | "function-bind": { 1259 | "version": "1.1.1", 1260 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1261 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 1262 | }, 1263 | "functional-red-black-tree": { 1264 | "version": "1.0.1", 1265 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1266 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 1267 | "dev": true 1268 | }, 1269 | "get-intrinsic": { 1270 | "version": "1.1.1", 1271 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", 1272 | "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", 1273 | "dev": true, 1274 | "requires": { 1275 | "function-bind": "^1.1.1", 1276 | "has": "^1.0.3", 1277 | "has-symbols": "^1.0.1" 1278 | } 1279 | }, 1280 | "get-symbol-description": { 1281 | "version": "1.0.0", 1282 | "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", 1283 | "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", 1284 | "dev": true, 1285 | "requires": { 1286 | "call-bind": "^1.0.2", 1287 | "get-intrinsic": "^1.1.1" 1288 | } 1289 | }, 1290 | "glob": { 1291 | "version": "7.2.0", 1292 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 1293 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 1294 | "dev": true, 1295 | "requires": { 1296 | "fs.realpath": "^1.0.0", 1297 | "inflight": "^1.0.4", 1298 | "inherits": "2", 1299 | "minimatch": "^3.0.4", 1300 | "once": "^1.3.0", 1301 | "path-is-absolute": "^1.0.0" 1302 | } 1303 | }, 1304 | "glob-parent": { 1305 | "version": "6.0.2", 1306 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 1307 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 1308 | "requires": { 1309 | "is-glob": "^4.0.3" 1310 | } 1311 | }, 1312 | "globals": { 1313 | "version": "13.12.1", 1314 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", 1315 | "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", 1316 | "dev": true, 1317 | "requires": { 1318 | "type-fest": "^0.20.2" 1319 | } 1320 | }, 1321 | "globby": { 1322 | "version": "11.1.0", 1323 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", 1324 | "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", 1325 | "dev": true, 1326 | "requires": { 1327 | "array-union": "^2.1.0", 1328 | "dir-glob": "^3.0.1", 1329 | "fast-glob": "^3.2.9", 1330 | "ignore": "^5.2.0", 1331 | "merge2": "^1.4.1", 1332 | "slash": "^3.0.0" 1333 | } 1334 | }, 1335 | "has": { 1336 | "version": "1.0.3", 1337 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1338 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1339 | "requires": { 1340 | "function-bind": "^1.1.1" 1341 | } 1342 | }, 1343 | "has-bigints": { 1344 | "version": "1.0.1", 1345 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", 1346 | "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", 1347 | "dev": true 1348 | }, 1349 | "has-flag": { 1350 | "version": "4.0.0", 1351 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1352 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 1353 | }, 1354 | "has-symbols": { 1355 | "version": "1.0.2", 1356 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", 1357 | "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", 1358 | "dev": true 1359 | }, 1360 | "has-tostringtag": { 1361 | "version": "1.0.0", 1362 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", 1363 | "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", 1364 | "dev": true, 1365 | "requires": { 1366 | "has-symbols": "^1.0.2" 1367 | } 1368 | }, 1369 | "ignore": { 1370 | "version": "5.2.0", 1371 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", 1372 | "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", 1373 | "dev": true 1374 | }, 1375 | "import-fresh": { 1376 | "version": "3.3.0", 1377 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1378 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1379 | "requires": { 1380 | "parent-module": "^1.0.0", 1381 | "resolve-from": "^4.0.0" 1382 | } 1383 | }, 1384 | "imurmurhash": { 1385 | "version": "0.1.4", 1386 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1387 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1388 | "dev": true 1389 | }, 1390 | "inflight": { 1391 | "version": "1.0.6", 1392 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1393 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1394 | "dev": true, 1395 | "requires": { 1396 | "once": "^1.3.0", 1397 | "wrappy": "1" 1398 | } 1399 | }, 1400 | "inherits": { 1401 | "version": "2.0.4", 1402 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1403 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1404 | "dev": true 1405 | }, 1406 | "internal-slot": { 1407 | "version": "1.0.3", 1408 | "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", 1409 | "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", 1410 | "dev": true, 1411 | "requires": { 1412 | "get-intrinsic": "^1.1.0", 1413 | "has": "^1.0.3", 1414 | "side-channel": "^1.0.4" 1415 | } 1416 | }, 1417 | "is-arrayish": { 1418 | "version": "0.2.1", 1419 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 1420 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" 1421 | }, 1422 | "is-bigint": { 1423 | "version": "1.0.4", 1424 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", 1425 | "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", 1426 | "dev": true, 1427 | "requires": { 1428 | "has-bigints": "^1.0.1" 1429 | } 1430 | }, 1431 | "is-binary-path": { 1432 | "version": "2.1.0", 1433 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1434 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1435 | "requires": { 1436 | "binary-extensions": "^2.0.0" 1437 | } 1438 | }, 1439 | "is-boolean-object": { 1440 | "version": "1.1.2", 1441 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", 1442 | "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", 1443 | "dev": true, 1444 | "requires": { 1445 | "call-bind": "^1.0.2", 1446 | "has-tostringtag": "^1.0.0" 1447 | } 1448 | }, 1449 | "is-callable": { 1450 | "version": "1.2.4", 1451 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", 1452 | "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", 1453 | "dev": true 1454 | }, 1455 | "is-core-module": { 1456 | "version": "2.8.1", 1457 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", 1458 | "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", 1459 | "requires": { 1460 | "has": "^1.0.3" 1461 | } 1462 | }, 1463 | "is-date-object": { 1464 | "version": "1.0.5", 1465 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", 1466 | "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", 1467 | "dev": true, 1468 | "requires": { 1469 | "has-tostringtag": "^1.0.0" 1470 | } 1471 | }, 1472 | "is-extglob": { 1473 | "version": "2.1.1", 1474 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1475 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" 1476 | }, 1477 | "is-glob": { 1478 | "version": "4.0.3", 1479 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1480 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1481 | "requires": { 1482 | "is-extglob": "^2.1.1" 1483 | } 1484 | }, 1485 | "is-negative-zero": { 1486 | "version": "2.0.2", 1487 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", 1488 | "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", 1489 | "dev": true 1490 | }, 1491 | "is-number": { 1492 | "version": "7.0.0", 1493 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1494 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" 1495 | }, 1496 | "is-number-object": { 1497 | "version": "1.0.6", 1498 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", 1499 | "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", 1500 | "dev": true, 1501 | "requires": { 1502 | "has-tostringtag": "^1.0.0" 1503 | } 1504 | }, 1505 | "is-regex": { 1506 | "version": "1.1.4", 1507 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", 1508 | "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", 1509 | "dev": true, 1510 | "requires": { 1511 | "call-bind": "^1.0.2", 1512 | "has-tostringtag": "^1.0.0" 1513 | } 1514 | }, 1515 | "is-shared-array-buffer": { 1516 | "version": "1.0.1", 1517 | "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", 1518 | "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", 1519 | "dev": true 1520 | }, 1521 | "is-string": { 1522 | "version": "1.0.7", 1523 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", 1524 | "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", 1525 | "dev": true, 1526 | "requires": { 1527 | "has-tostringtag": "^1.0.0" 1528 | } 1529 | }, 1530 | "is-symbol": { 1531 | "version": "1.0.4", 1532 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 1533 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 1534 | "dev": true, 1535 | "requires": { 1536 | "has-symbols": "^1.0.2" 1537 | } 1538 | }, 1539 | "is-weakref": { 1540 | "version": "1.0.2", 1541 | "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", 1542 | "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", 1543 | "dev": true, 1544 | "requires": { 1545 | "call-bind": "^1.0.2" 1546 | } 1547 | }, 1548 | "isexe": { 1549 | "version": "2.0.0", 1550 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1551 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1552 | "dev": true 1553 | }, 1554 | "javascript-time-ago": { 1555 | "version": "2.3.11", 1556 | "resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.3.11.tgz", 1557 | "integrity": "sha512-R6Ux0IGv7RmAZ7vB04r/gevGaLDJeZY7+6jTYyYsPAF5x4PSv6up+dW2hLK99+OUY8xwdeXPItZFiUppIRUaoQ==", 1558 | "requires": { 1559 | "relative-time-format": "^1.0.6" 1560 | } 1561 | }, 1562 | "js-tokens": { 1563 | "version": "4.0.0", 1564 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1565 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 1566 | }, 1567 | "js-yaml": { 1568 | "version": "4.1.0", 1569 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1570 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1571 | "dev": true, 1572 | "requires": { 1573 | "argparse": "^2.0.1" 1574 | } 1575 | }, 1576 | "json-parse-even-better-errors": { 1577 | "version": "2.3.1", 1578 | "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", 1579 | "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" 1580 | }, 1581 | "json-schema-traverse": { 1582 | "version": "0.4.1", 1583 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1584 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1585 | "dev": true 1586 | }, 1587 | "json-stable-stringify-without-jsonify": { 1588 | "version": "1.0.1", 1589 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1590 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1591 | "dev": true 1592 | }, 1593 | "json5": { 1594 | "version": "1.0.1", 1595 | "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", 1596 | "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", 1597 | "dev": true, 1598 | "requires": { 1599 | "minimist": "^1.2.0" 1600 | } 1601 | }, 1602 | "jsx-ast-utils": { 1603 | "version": "3.2.1", 1604 | "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", 1605 | "integrity": "sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==", 1606 | "dev": true, 1607 | "requires": { 1608 | "array-includes": "^3.1.3", 1609 | "object.assign": "^4.1.2" 1610 | } 1611 | }, 1612 | "language-subtag-registry": { 1613 | "version": "0.3.21", 1614 | "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz", 1615 | "integrity": "sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==", 1616 | "dev": true 1617 | }, 1618 | "language-tags": { 1619 | "version": "1.0.5", 1620 | "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", 1621 | "integrity": "sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=", 1622 | "dev": true, 1623 | "requires": { 1624 | "language-subtag-registry": "~0.3.2" 1625 | } 1626 | }, 1627 | "levn": { 1628 | "version": "0.4.1", 1629 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1630 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1631 | "dev": true, 1632 | "requires": { 1633 | "prelude-ls": "^1.2.1", 1634 | "type-check": "~0.4.0" 1635 | } 1636 | }, 1637 | "lilconfig": { 1638 | "version": "2.0.4", 1639 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", 1640 | "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==" 1641 | }, 1642 | "lines-and-columns": { 1643 | "version": "1.2.4", 1644 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", 1645 | "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" 1646 | }, 1647 | "locate-path": { 1648 | "version": "2.0.0", 1649 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 1650 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 1651 | "dev": true, 1652 | "requires": { 1653 | "p-locate": "^2.0.0", 1654 | "path-exists": "^3.0.0" 1655 | } 1656 | }, 1657 | "lodash.merge": { 1658 | "version": "4.6.2", 1659 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1660 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1661 | "dev": true 1662 | }, 1663 | "loose-envify": { 1664 | "version": "1.4.0", 1665 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 1666 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 1667 | "requires": { 1668 | "js-tokens": "^3.0.0 || ^4.0.0" 1669 | } 1670 | }, 1671 | "lru-cache": { 1672 | "version": "6.0.0", 1673 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1674 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1675 | "dev": true, 1676 | "requires": { 1677 | "yallist": "^4.0.0" 1678 | } 1679 | }, 1680 | "merge2": { 1681 | "version": "1.4.1", 1682 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1683 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" 1684 | }, 1685 | "micromatch": { 1686 | "version": "4.0.4", 1687 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", 1688 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", 1689 | "requires": { 1690 | "braces": "^3.0.1", 1691 | "picomatch": "^2.2.3" 1692 | } 1693 | }, 1694 | "minimatch": { 1695 | "version": "3.0.4", 1696 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1697 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1698 | "dev": true, 1699 | "requires": { 1700 | "brace-expansion": "^1.1.7" 1701 | } 1702 | }, 1703 | "minimist": { 1704 | "version": "1.2.5", 1705 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1706 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" 1707 | }, 1708 | "ms": { 1709 | "version": "2.1.2", 1710 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1711 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1712 | "dev": true 1713 | }, 1714 | "nanoid": { 1715 | "version": "3.2.0", 1716 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", 1717 | "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==" 1718 | }, 1719 | "natural-compare": { 1720 | "version": "1.4.0", 1721 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1722 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1723 | "dev": true 1724 | }, 1725 | "next": { 1726 | "version": "12.0.10", 1727 | "resolved": "https://registry.npmjs.org/next/-/next-12.0.10.tgz", 1728 | "integrity": "sha512-1y3PpGzpb/EZzz1jgne+JfZXKAVJUjYXwxzrADf/LWN+8yi9o79vMLXpW3mevvCHkEF2sBnIdjzNn16TJrINUw==", 1729 | "requires": { 1730 | "@next/env": "12.0.10", 1731 | "@next/swc-android-arm64": "12.0.10", 1732 | "@next/swc-darwin-arm64": "12.0.10", 1733 | "@next/swc-darwin-x64": "12.0.10", 1734 | "@next/swc-linux-arm-gnueabihf": "12.0.10", 1735 | "@next/swc-linux-arm64-gnu": "12.0.10", 1736 | "@next/swc-linux-arm64-musl": "12.0.10", 1737 | "@next/swc-linux-x64-gnu": "12.0.10", 1738 | "@next/swc-linux-x64-musl": "12.0.10", 1739 | "@next/swc-win32-arm64-msvc": "12.0.10", 1740 | "@next/swc-win32-ia32-msvc": "12.0.10", 1741 | "@next/swc-win32-x64-msvc": "12.0.10", 1742 | "caniuse-lite": "^1.0.30001283", 1743 | "postcss": "8.4.5", 1744 | "styled-jsx": "5.0.0", 1745 | "use-subscription": "1.5.1" 1746 | }, 1747 | "dependencies": { 1748 | "postcss": { 1749 | "version": "8.4.5", 1750 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.5.tgz", 1751 | "integrity": "sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==", 1752 | "requires": { 1753 | "nanoid": "^3.1.30", 1754 | "picocolors": "^1.0.0", 1755 | "source-map-js": "^1.0.1" 1756 | } 1757 | } 1758 | } 1759 | }, 1760 | "node-releases": { 1761 | "version": "2.0.1", 1762 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", 1763 | "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" 1764 | }, 1765 | "normalize-path": { 1766 | "version": "3.0.0", 1767 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1768 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" 1769 | }, 1770 | "normalize-range": { 1771 | "version": "0.1.2", 1772 | "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", 1773 | "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=" 1774 | }, 1775 | "object-assign": { 1776 | "version": "4.1.1", 1777 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1778 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1779 | }, 1780 | "object-hash": { 1781 | "version": "2.2.0", 1782 | "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", 1783 | "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" 1784 | }, 1785 | "object-inspect": { 1786 | "version": "1.12.0", 1787 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", 1788 | "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", 1789 | "dev": true 1790 | }, 1791 | "object-keys": { 1792 | "version": "1.1.1", 1793 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1794 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1795 | "dev": true 1796 | }, 1797 | "object.assign": { 1798 | "version": "4.1.2", 1799 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", 1800 | "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", 1801 | "dev": true, 1802 | "requires": { 1803 | "call-bind": "^1.0.0", 1804 | "define-properties": "^1.1.3", 1805 | "has-symbols": "^1.0.1", 1806 | "object-keys": "^1.1.1" 1807 | } 1808 | }, 1809 | "object.entries": { 1810 | "version": "1.1.5", 1811 | "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", 1812 | "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", 1813 | "dev": true, 1814 | "requires": { 1815 | "call-bind": "^1.0.2", 1816 | "define-properties": "^1.1.3", 1817 | "es-abstract": "^1.19.1" 1818 | } 1819 | }, 1820 | "object.fromentries": { 1821 | "version": "2.0.5", 1822 | "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", 1823 | "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", 1824 | "dev": true, 1825 | "requires": { 1826 | "call-bind": "^1.0.2", 1827 | "define-properties": "^1.1.3", 1828 | "es-abstract": "^1.19.1" 1829 | } 1830 | }, 1831 | "object.hasown": { 1832 | "version": "1.1.0", 1833 | "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.0.tgz", 1834 | "integrity": "sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==", 1835 | "dev": true, 1836 | "requires": { 1837 | "define-properties": "^1.1.3", 1838 | "es-abstract": "^1.19.1" 1839 | } 1840 | }, 1841 | "object.values": { 1842 | "version": "1.1.5", 1843 | "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", 1844 | "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", 1845 | "dev": true, 1846 | "requires": { 1847 | "call-bind": "^1.0.2", 1848 | "define-properties": "^1.1.3", 1849 | "es-abstract": "^1.19.1" 1850 | } 1851 | }, 1852 | "once": { 1853 | "version": "1.4.0", 1854 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1855 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1856 | "dev": true, 1857 | "requires": { 1858 | "wrappy": "1" 1859 | } 1860 | }, 1861 | "optionator": { 1862 | "version": "0.9.1", 1863 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 1864 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 1865 | "dev": true, 1866 | "requires": { 1867 | "deep-is": "^0.1.3", 1868 | "fast-levenshtein": "^2.0.6", 1869 | "levn": "^0.4.1", 1870 | "prelude-ls": "^1.2.1", 1871 | "type-check": "^0.4.0", 1872 | "word-wrap": "^1.2.3" 1873 | } 1874 | }, 1875 | "p-limit": { 1876 | "version": "1.3.0", 1877 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", 1878 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", 1879 | "dev": true, 1880 | "requires": { 1881 | "p-try": "^1.0.0" 1882 | } 1883 | }, 1884 | "p-locate": { 1885 | "version": "2.0.0", 1886 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 1887 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 1888 | "dev": true, 1889 | "requires": { 1890 | "p-limit": "^1.1.0" 1891 | } 1892 | }, 1893 | "p-try": { 1894 | "version": "1.0.0", 1895 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", 1896 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", 1897 | "dev": true 1898 | }, 1899 | "parent-module": { 1900 | "version": "1.0.1", 1901 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1902 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1903 | "requires": { 1904 | "callsites": "^3.0.0" 1905 | } 1906 | }, 1907 | "parse-json": { 1908 | "version": "5.2.0", 1909 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", 1910 | "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", 1911 | "requires": { 1912 | "@babel/code-frame": "^7.0.0", 1913 | "error-ex": "^1.3.1", 1914 | "json-parse-even-better-errors": "^2.3.0", 1915 | "lines-and-columns": "^1.1.6" 1916 | } 1917 | }, 1918 | "path-exists": { 1919 | "version": "3.0.0", 1920 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1921 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1922 | "dev": true 1923 | }, 1924 | "path-is-absolute": { 1925 | "version": "1.0.1", 1926 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1927 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1928 | "dev": true 1929 | }, 1930 | "path-key": { 1931 | "version": "3.1.1", 1932 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1933 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1934 | "dev": true 1935 | }, 1936 | "path-parse": { 1937 | "version": "1.0.7", 1938 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1939 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 1940 | }, 1941 | "path-type": { 1942 | "version": "4.0.0", 1943 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 1944 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" 1945 | }, 1946 | "picocolors": { 1947 | "version": "1.0.0", 1948 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", 1949 | "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" 1950 | }, 1951 | "picomatch": { 1952 | "version": "2.3.1", 1953 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1954 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" 1955 | }, 1956 | "postcss": { 1957 | "version": "8.4.6", 1958 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", 1959 | "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", 1960 | "requires": { 1961 | "nanoid": "^3.2.0", 1962 | "picocolors": "^1.0.0", 1963 | "source-map-js": "^1.0.2" 1964 | } 1965 | }, 1966 | "postcss-js": { 1967 | "version": "4.0.0", 1968 | "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", 1969 | "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", 1970 | "requires": { 1971 | "camelcase-css": "^2.0.1" 1972 | } 1973 | }, 1974 | "postcss-load-config": { 1975 | "version": "3.1.1", 1976 | "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.1.tgz", 1977 | "integrity": "sha512-c/9XYboIbSEUZpiD1UQD0IKiUe8n9WHYV7YFe7X7J+ZwCsEKkUJSFWjS9hBU1RR9THR7jMXst8sxiqP0jjo2mg==", 1978 | "requires": { 1979 | "lilconfig": "^2.0.4", 1980 | "yaml": "^1.10.2" 1981 | } 1982 | }, 1983 | "postcss-nested": { 1984 | "version": "5.0.6", 1985 | "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", 1986 | "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", 1987 | "requires": { 1988 | "postcss-selector-parser": "^6.0.6" 1989 | } 1990 | }, 1991 | "postcss-selector-parser": { 1992 | "version": "6.0.9", 1993 | "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", 1994 | "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", 1995 | "requires": { 1996 | "cssesc": "^3.0.0", 1997 | "util-deprecate": "^1.0.2" 1998 | } 1999 | }, 2000 | "postcss-value-parser": { 2001 | "version": "4.2.0", 2002 | "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", 2003 | "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" 2004 | }, 2005 | "prelude-ls": { 2006 | "version": "1.2.1", 2007 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2008 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2009 | "dev": true 2010 | }, 2011 | "prop-types": { 2012 | "version": "15.8.1", 2013 | "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", 2014 | "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", 2015 | "dev": true, 2016 | "requires": { 2017 | "loose-envify": "^1.4.0", 2018 | "object-assign": "^4.1.1", 2019 | "react-is": "^16.13.1" 2020 | } 2021 | }, 2022 | "punycode": { 2023 | "version": "2.1.1", 2024 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 2025 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 2026 | "dev": true 2027 | }, 2028 | "queue-microtask": { 2029 | "version": "1.2.3", 2030 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 2031 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" 2032 | }, 2033 | "quick-lru": { 2034 | "version": "5.1.1", 2035 | "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", 2036 | "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" 2037 | }, 2038 | "react": { 2039 | "version": "17.0.2", 2040 | "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", 2041 | "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", 2042 | "requires": { 2043 | "loose-envify": "^1.1.0", 2044 | "object-assign": "^4.1.1" 2045 | } 2046 | }, 2047 | "react-dom": { 2048 | "version": "17.0.2", 2049 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", 2050 | "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", 2051 | "requires": { 2052 | "loose-envify": "^1.1.0", 2053 | "object-assign": "^4.1.1", 2054 | "scheduler": "^0.20.2" 2055 | } 2056 | }, 2057 | "react-is": { 2058 | "version": "16.13.1", 2059 | "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", 2060 | "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", 2061 | "dev": true 2062 | }, 2063 | "readdirp": { 2064 | "version": "3.6.0", 2065 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2066 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2067 | "requires": { 2068 | "picomatch": "^2.2.1" 2069 | } 2070 | }, 2071 | "regenerator-runtime": { 2072 | "version": "0.13.9", 2073 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", 2074 | "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", 2075 | "dev": true 2076 | }, 2077 | "regexp.prototype.flags": { 2078 | "version": "1.4.1", 2079 | "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", 2080 | "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", 2081 | "dev": true, 2082 | "requires": { 2083 | "call-bind": "^1.0.2", 2084 | "define-properties": "^1.1.3" 2085 | } 2086 | }, 2087 | "regexpp": { 2088 | "version": "3.2.0", 2089 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 2090 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 2091 | "dev": true 2092 | }, 2093 | "relative-time-format": { 2094 | "version": "1.0.6", 2095 | "resolved": "https://registry.npmjs.org/relative-time-format/-/relative-time-format-1.0.6.tgz", 2096 | "integrity": "sha512-voemOJLxlKun4P1fAo4PEg2WXNGjhqfE/G8Xen4gcy24Hyu/djn5bT5axmhx4MnjynoZ8f0HCOjk3RZpsY6X/g==" 2097 | }, 2098 | "resolve": { 2099 | "version": "1.22.0", 2100 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", 2101 | "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", 2102 | "requires": { 2103 | "is-core-module": "^2.8.1", 2104 | "path-parse": "^1.0.7", 2105 | "supports-preserve-symlinks-flag": "^1.0.0" 2106 | } 2107 | }, 2108 | "resolve-from": { 2109 | "version": "4.0.0", 2110 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2111 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" 2112 | }, 2113 | "reusify": { 2114 | "version": "1.0.4", 2115 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2116 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" 2117 | }, 2118 | "rimraf": { 2119 | "version": "3.0.2", 2120 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2121 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2122 | "dev": true, 2123 | "requires": { 2124 | "glob": "^7.1.3" 2125 | } 2126 | }, 2127 | "run-parallel": { 2128 | "version": "1.2.0", 2129 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 2130 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 2131 | "requires": { 2132 | "queue-microtask": "^1.2.2" 2133 | } 2134 | }, 2135 | "scheduler": { 2136 | "version": "0.20.2", 2137 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", 2138 | "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", 2139 | "requires": { 2140 | "loose-envify": "^1.1.0", 2141 | "object-assign": "^4.1.1" 2142 | } 2143 | }, 2144 | "semver": { 2145 | "version": "7.3.5", 2146 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 2147 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 2148 | "dev": true, 2149 | "requires": { 2150 | "lru-cache": "^6.0.0" 2151 | } 2152 | }, 2153 | "shebang-command": { 2154 | "version": "2.0.0", 2155 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2156 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2157 | "dev": true, 2158 | "requires": { 2159 | "shebang-regex": "^3.0.0" 2160 | } 2161 | }, 2162 | "shebang-regex": { 2163 | "version": "3.0.0", 2164 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2165 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2166 | "dev": true 2167 | }, 2168 | "side-channel": { 2169 | "version": "1.0.4", 2170 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 2171 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 2172 | "dev": true, 2173 | "requires": { 2174 | "call-bind": "^1.0.0", 2175 | "get-intrinsic": "^1.0.2", 2176 | "object-inspect": "^1.9.0" 2177 | } 2178 | }, 2179 | "slash": { 2180 | "version": "3.0.0", 2181 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 2182 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2183 | "dev": true 2184 | }, 2185 | "source-map-js": { 2186 | "version": "1.0.2", 2187 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", 2188 | "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" 2189 | }, 2190 | "string.prototype.matchall": { 2191 | "version": "4.0.6", 2192 | "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz", 2193 | "integrity": "sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==", 2194 | "dev": true, 2195 | "requires": { 2196 | "call-bind": "^1.0.2", 2197 | "define-properties": "^1.1.3", 2198 | "es-abstract": "^1.19.1", 2199 | "get-intrinsic": "^1.1.1", 2200 | "has-symbols": "^1.0.2", 2201 | "internal-slot": "^1.0.3", 2202 | "regexp.prototype.flags": "^1.3.1", 2203 | "side-channel": "^1.0.4" 2204 | } 2205 | }, 2206 | "string.prototype.trimend": { 2207 | "version": "1.0.4", 2208 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", 2209 | "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", 2210 | "dev": true, 2211 | "requires": { 2212 | "call-bind": "^1.0.2", 2213 | "define-properties": "^1.1.3" 2214 | } 2215 | }, 2216 | "string.prototype.trimstart": { 2217 | "version": "1.0.4", 2218 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", 2219 | "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", 2220 | "dev": true, 2221 | "requires": { 2222 | "call-bind": "^1.0.2", 2223 | "define-properties": "^1.1.3" 2224 | } 2225 | }, 2226 | "strip-ansi": { 2227 | "version": "6.0.1", 2228 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2229 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2230 | "dev": true, 2231 | "requires": { 2232 | "ansi-regex": "^5.0.1" 2233 | } 2234 | }, 2235 | "strip-bom": { 2236 | "version": "3.0.0", 2237 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 2238 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 2239 | "dev": true 2240 | }, 2241 | "strip-json-comments": { 2242 | "version": "3.1.1", 2243 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2244 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2245 | "dev": true 2246 | }, 2247 | "styled-jsx": { 2248 | "version": "5.0.0", 2249 | "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.0.tgz", 2250 | "integrity": "sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==" 2251 | }, 2252 | "supports-color": { 2253 | "version": "7.2.0", 2254 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2255 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2256 | "requires": { 2257 | "has-flag": "^4.0.0" 2258 | } 2259 | }, 2260 | "supports-preserve-symlinks-flag": { 2261 | "version": "1.0.0", 2262 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 2263 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" 2264 | }, 2265 | "swr": { 2266 | "version": "1.2.1", 2267 | "resolved": "https://registry.npmjs.org/swr/-/swr-1.2.1.tgz", 2268 | "integrity": "sha512-1cuWXqJqXcFwbgONGCY4PHZ8v05009JdHsC3CIC6u7d00kgbMswNr1sHnnhseOBxtzVqcCNpOHEgVDciRer45w==" 2269 | }, 2270 | "tailwindcss": { 2271 | "version": "3.0.18", 2272 | "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.18.tgz", 2273 | "integrity": "sha512-ihPTpEyA5ANgZbwKlgrbfnzOp9R5vDHFWmqxB1PT8NwOGCOFVVMl+Ps1cQQ369acaqqf1BEF77roCwK0lvNmTw==", 2274 | "requires": { 2275 | "arg": "^5.0.1", 2276 | "chalk": "^4.1.2", 2277 | "chokidar": "^3.5.3", 2278 | "color-name": "^1.1.4", 2279 | "cosmiconfig": "^7.0.1", 2280 | "detective": "^5.2.0", 2281 | "didyoumean": "^1.2.2", 2282 | "dlv": "^1.1.3", 2283 | "fast-glob": "^3.2.11", 2284 | "glob-parent": "^6.0.2", 2285 | "is-glob": "^4.0.3", 2286 | "normalize-path": "^3.0.0", 2287 | "object-hash": "^2.2.0", 2288 | "postcss-js": "^4.0.0", 2289 | "postcss-load-config": "^3.1.0", 2290 | "postcss-nested": "5.0.6", 2291 | "postcss-selector-parser": "^6.0.9", 2292 | "postcss-value-parser": "^4.2.0", 2293 | "quick-lru": "^5.1.1", 2294 | "resolve": "^1.21.0" 2295 | } 2296 | }, 2297 | "text-table": { 2298 | "version": "0.2.0", 2299 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2300 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2301 | "dev": true 2302 | }, 2303 | "to-regex-range": { 2304 | "version": "5.0.1", 2305 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2306 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2307 | "requires": { 2308 | "is-number": "^7.0.0" 2309 | } 2310 | }, 2311 | "tsconfig-paths": { 2312 | "version": "3.12.0", 2313 | "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", 2314 | "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", 2315 | "dev": true, 2316 | "requires": { 2317 | "@types/json5": "^0.0.29", 2318 | "json5": "^1.0.1", 2319 | "minimist": "^1.2.0", 2320 | "strip-bom": "^3.0.0" 2321 | } 2322 | }, 2323 | "tslib": { 2324 | "version": "1.14.1", 2325 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 2326 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 2327 | "dev": true 2328 | }, 2329 | "tsutils": { 2330 | "version": "3.21.0", 2331 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", 2332 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", 2333 | "dev": true, 2334 | "requires": { 2335 | "tslib": "^1.8.1" 2336 | } 2337 | }, 2338 | "type-check": { 2339 | "version": "0.4.0", 2340 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2341 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2342 | "dev": true, 2343 | "requires": { 2344 | "prelude-ls": "^1.2.1" 2345 | } 2346 | }, 2347 | "type-fest": { 2348 | "version": "0.20.2", 2349 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2350 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2351 | "dev": true 2352 | }, 2353 | "typescript": { 2354 | "version": "4.5.5", 2355 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", 2356 | "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", 2357 | "dev": true 2358 | }, 2359 | "unbox-primitive": { 2360 | "version": "1.0.1", 2361 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", 2362 | "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", 2363 | "dev": true, 2364 | "requires": { 2365 | "function-bind": "^1.1.1", 2366 | "has-bigints": "^1.0.1", 2367 | "has-symbols": "^1.0.2", 2368 | "which-boxed-primitive": "^1.0.2" 2369 | } 2370 | }, 2371 | "uri-js": { 2372 | "version": "4.4.1", 2373 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2374 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2375 | "dev": true, 2376 | "requires": { 2377 | "punycode": "^2.1.0" 2378 | } 2379 | }, 2380 | "use-subscription": { 2381 | "version": "1.5.1", 2382 | "resolved": "https://registry.npmjs.org/use-subscription/-/use-subscription-1.5.1.tgz", 2383 | "integrity": "sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==", 2384 | "requires": { 2385 | "object-assign": "^4.1.1" 2386 | } 2387 | }, 2388 | "util-deprecate": { 2389 | "version": "1.0.2", 2390 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2391 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2392 | }, 2393 | "v8-compile-cache": { 2394 | "version": "2.3.0", 2395 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 2396 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 2397 | "dev": true 2398 | }, 2399 | "which": { 2400 | "version": "2.0.2", 2401 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2402 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2403 | "dev": true, 2404 | "requires": { 2405 | "isexe": "^2.0.0" 2406 | } 2407 | }, 2408 | "which-boxed-primitive": { 2409 | "version": "1.0.2", 2410 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 2411 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 2412 | "dev": true, 2413 | "requires": { 2414 | "is-bigint": "^1.0.1", 2415 | "is-boolean-object": "^1.1.0", 2416 | "is-number-object": "^1.0.4", 2417 | "is-string": "^1.0.5", 2418 | "is-symbol": "^1.0.3" 2419 | } 2420 | }, 2421 | "word-wrap": { 2422 | "version": "1.2.3", 2423 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2424 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2425 | "dev": true 2426 | }, 2427 | "wrappy": { 2428 | "version": "1.0.2", 2429 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2430 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2431 | "dev": true 2432 | }, 2433 | "xtend": { 2434 | "version": "4.0.2", 2435 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 2436 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 2437 | }, 2438 | "yallist": { 2439 | "version": "4.0.0", 2440 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2441 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2442 | "dev": true 2443 | }, 2444 | "yaml": { 2445 | "version": "1.10.2", 2446 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", 2447 | "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" 2448 | } 2449 | } 2450 | } 2451 | -------------------------------------------------------------------------------- /nextjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs", 3 | "private": true, 4 | "scripts": { 5 | "dev": "next dev", 6 | "build": "next build", 7 | "start": "next start", 8 | "lint": "next lint" 9 | }, 10 | "dependencies": { 11 | "@fortawesome/fontawesome-free": "^5.15.4", 12 | "autoprefixer": "^10.4.2", 13 | "axios": "^0.25.0", 14 | "javascript-time-ago": "^2.3.11", 15 | "next": "12.0.10", 16 | "postcss": "^8.4.6", 17 | "react": "17.0.2", 18 | "react-dom": "17.0.2", 19 | "swr": "^1.2.1", 20 | "tailwindcss": "^3.0.18" 21 | }, 22 | "devDependencies": { 23 | "@types/node": "17.0.15", 24 | "@types/react": "17.0.39", 25 | "eslint": "8.8.0", 26 | "eslint-config-next": "12.0.10", 27 | "typescript": "4.5.5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /nextjs/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /nextjs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeedu/imersao-fc6/19a03481f3ead5bf4fe22e1c5447de842b29829b/nextjs/public/favicon.ico -------------------------------------------------------------------------------- /nextjs/public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /nextjs/src/components/Button.tsx: -------------------------------------------------------------------------------- 1 | type ButtonProps = React.ButtonHTMLAttributes; 2 | export const Button: React.FunctionComponent = (props) => { 3 | return ( 4 | 9 | {props.children} 10 | 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /nextjs/src/components/Navbar.tsx: -------------------------------------------------------------------------------- 1 | // @flow 2 | import * as React from "react"; 3 | import { toggleTheme } from "../utils/theme"; 4 | import Link from "next/link"; 5 | type Props = {}; 6 | export const Navbar = (props: Props) => { 7 | return ( 8 | 9 | {/* */} 10 | 11 | 12 | 13 | Tweecycle 14 | 15 | 19 | 23 | 24 | 25 | 29 | Tweets 30 | 31 | 32 | 33 | 34 | 35 | 36 | E-mails 37 | 38 | 39 | 40 | 41 | 42 | toggleTheme()} 46 | > 47 | Theme 48 | 49 | 50 | 51 | 52 | 53 | 54 | ); 55 | }; 56 | -------------------------------------------------------------------------------- /nextjs/src/components/Title.tsx: -------------------------------------------------------------------------------- 1 | type TitleProps = {}; 2 | export const Title: React.FunctionComponent = (props) => { 3 | return ( 4 | {props.children} 5 | ); 6 | }; 7 | -------------------------------------------------------------------------------- /nextjs/src/components/Tweet.tsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import * as React from "react"; 3 | import { Tweet as TweetModel } from "../utils/models"; 4 | import TimeAgo from "javascript-time-ago"; 5 | import pt from "javascript-time-ago/locale/pt-PT.json"; 6 | 7 | TimeAgo.addDefaultLocale(pt); 8 | const timeAgo = new TimeAgo("pt-PT"); 9 | 10 | type TweetProps = { 11 | tweet: TweetModel; 12 | }; 13 | export const Tweet: React.FunctionComponent = (props) => { 14 | const { tweet } = props; 15 | return ( 16 | <> 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | {tweet.User.Name} 32 | 33 | @{tweet.User.ScreenName} . {timeAgo.format(tweet.CreatedAt)} 34 | 35 | 36 | 37 | 38 | 39 | 40 | {tweet.Text} 41 | 42 | 43 | > 44 | ); 45 | }; 46 | -------------------------------------------------------------------------------- /nextjs/src/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import "../styles/globals.css"; 2 | import type { AppProps } from "next/app"; 3 | import { Navbar } from "../components/Navbar"; 4 | 5 | function MyApp({ Component, pageProps }: AppProps) { 6 | return ( 7 | <> 8 | 9 | 10 | 11 | 12 | > 13 | ); 14 | } 15 | 16 | export default MyApp; 17 | -------------------------------------------------------------------------------- /nextjs/src/pages/api/hello.ts: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | import type { NextApiRequest, NextApiResponse } from 'next' 3 | 4 | type Data = { 5 | name: string 6 | } 7 | 8 | export default function handler( 9 | req: NextApiRequest, 10 | res: NextApiResponse 11 | ) { 12 | res.status(200).json({ name: 'John Doe' }) 13 | } 14 | -------------------------------------------------------------------------------- /nextjs/src/pages/emails.tsx: -------------------------------------------------------------------------------- 1 | import { NextPage } from "next"; 2 | import useSWR from "swr"; 3 | import { Title } from "../components/Title"; 4 | import http from "../utils/http"; 5 | import { FormEvent } from "react"; 6 | import { Button } from "../components/Button"; 7 | 8 | const fetcher = (url: string) => 9 | http.get(url).then((res) => (res.data === "" ? [] : res.data.emails)); 10 | 11 | const EmailsPage: NextPage = () => { 12 | const { data } = useSWR("mail-list", fetcher, { fallbackData: [] }); 13 | 14 | async function onSubmit(event: FormEvent) { 15 | event.preventDefault(); 16 | const emailsTextarea = document.getElementById( 17 | "emails" 18 | ) as HTMLTextAreaElement; 19 | await http.post("mail-list", { emails: emailsTextarea.value.split("\n") }); 20 | } 21 | 22 | return ( 23 | 24 | Emails 25 | 26 | 27 | 28 | 34 | 35 | Salvar 36 | 37 | 38 | ); 39 | }; 40 | 41 | export default EmailsPage; 42 | -------------------------------------------------------------------------------- /nextjs/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import type { NextPage } from 'next' 2 | import Head from 'next/head' 3 | import Image from 'next/image' 4 | import styles from '../styles/Home.module.css' 5 | 6 | const Home: NextPage = () => { 7 | return ( 8 | 9 | 10 | Create Next App 11 | 12 | 13 | 14 | 15 | 16 | 17 | Welcome to Next.js! 18 | 19 | 20 | 21 | Get started by editing{' '} 22 | pages/index.tsx 23 | 24 | 25 | 26 | 27 | Documentation → 28 | Find in-depth information about Next.js features and API. 29 | 30 | 31 | 32 | Learn → 33 | Learn about Next.js in an interactive course with quizzes! 34 | 35 | 36 | 40 | Examples → 41 | Discover and deploy boilerplate example Next.js projects. 42 | 43 | 44 | 48 | Deploy → 49 | 50 | Instantly deploy your Next.js site to a public URL with Vercel. 51 | 52 | 53 | 54 | 55 | 56 | 68 | 69 | ) 70 | } 71 | 72 | export default Home 73 | -------------------------------------------------------------------------------- /nextjs/src/pages/pagina1.tsx: -------------------------------------------------------------------------------- 1 | import { GetServerSideProps, NextPage } from "next"; 2 | 3 | type Pagina1PageProps = { 4 | name: string; 5 | } 6 | 7 | const Pagina1Page: NextPage = (props) => { 8 | return Hello World!! {props.name}; 9 | }; 10 | 11 | export const getServerSideProps: GetServerSideProps = async (context) => { 12 | return { 13 | props: { 14 | name: "Full Cycle", 15 | }, 16 | }; 17 | }; 18 | 19 | export default Pagina1Page; 20 | -------------------------------------------------------------------------------- /nextjs/src/pages/tweets.tsx: -------------------------------------------------------------------------------- 1 | import { NextPage } from "next"; 2 | import useSWR from "swr"; 3 | import { Title } from "../components/Title"; 4 | import http from "../utils/http"; 5 | import { Tweet as TweetModel } from "../utils/models"; 6 | import { Tweet } from "../components/Tweet"; 7 | 8 | const fetcher = (url: string) => http.get(url).then((res) => res.data); 9 | 10 | const TweetsPage: NextPage = () => { 11 | const { data: tweets } = useSWR("tweets", fetcher, { 12 | refreshInterval: 5000, 13 | }); 14 | 15 | return ( 16 | 17 | Tweets 18 | {tweets?.map((t, key) => ( 19 | 20 | ))} 21 | 22 | ); 23 | }; 24 | 25 | export default TweetsPage; 26 | -------------------------------------------------------------------------------- /nextjs/src/styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | padding: 0 2rem; 3 | } 4 | 5 | .main { 6 | min-height: 100vh; 7 | padding: 4rem 0; 8 | flex: 1; 9 | display: flex; 10 | flex-direction: column; 11 | justify-content: center; 12 | align-items: center; 13 | } 14 | 15 | .footer { 16 | display: flex; 17 | flex: 1; 18 | padding: 2rem 0; 19 | border-top: 1px solid #eaeaea; 20 | justify-content: center; 21 | align-items: center; 22 | } 23 | 24 | .footer a { 25 | display: flex; 26 | justify-content: center; 27 | align-items: center; 28 | flex-grow: 1; 29 | } 30 | 31 | .title a { 32 | color: #0070f3; 33 | text-decoration: none; 34 | } 35 | 36 | .title a:hover, 37 | .title a:focus, 38 | .title a:active { 39 | text-decoration: underline; 40 | } 41 | 42 | .title { 43 | margin: 0; 44 | line-height: 1.15; 45 | font-size: 4rem; 46 | } 47 | 48 | .title, 49 | .description { 50 | text-align: center; 51 | } 52 | 53 | .description { 54 | margin: 4rem 0; 55 | line-height: 1.5; 56 | font-size: 1.5rem; 57 | } 58 | 59 | .code { 60 | background: #fafafa; 61 | border-radius: 5px; 62 | padding: 0.75rem; 63 | font-size: 1.1rem; 64 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, 65 | Bitstream Vera Sans Mono, Courier New, monospace; 66 | } 67 | 68 | .grid { 69 | display: flex; 70 | align-items: center; 71 | justify-content: center; 72 | flex-wrap: wrap; 73 | max-width: 800px; 74 | } 75 | 76 | .card { 77 | margin: 1rem; 78 | padding: 1.5rem; 79 | text-align: left; 80 | color: inherit; 81 | text-decoration: none; 82 | border: 1px solid #eaeaea; 83 | border-radius: 10px; 84 | transition: color 0.15s ease, border-color 0.15s ease; 85 | max-width: 300px; 86 | } 87 | 88 | .card:hover, 89 | .card:focus, 90 | .card:active { 91 | color: #0070f3; 92 | border-color: #0070f3; 93 | } 94 | 95 | .card h2 { 96 | margin: 0 0 1rem 0; 97 | font-size: 1.5rem; 98 | } 99 | 100 | .card p { 101 | margin: 0; 102 | font-size: 1.25rem; 103 | line-height: 1.5; 104 | } 105 | 106 | .logo { 107 | height: 1em; 108 | margin-left: 0.5rem; 109 | } 110 | 111 | @media (max-width: 600px) { 112 | .grid { 113 | width: 100%; 114 | flex-direction: column; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /nextjs/src/styles/globals.css: -------------------------------------------------------------------------------- 1 | @import "~@fortawesome/fontawesome-free/css/fontawesome.css"; 2 | @import "~@fortawesome/fontawesome-free/css/solid.css"; 3 | @import "~@fortawesome/fontawesome-free/css/brands.css"; 4 | 5 | @tailwind base; 6 | @tailwind components; 7 | @tailwind utilities; 8 | 9 | :root{ 10 | --color-background: #FFFFFF; 11 | --dark-color-background: #111827; 12 | } 13 | 14 | [class="dark"]{ 15 | --color-background: var(--dark-color-background); 16 | } 17 | 18 | @layer base{ 19 | body{ 20 | background-color: var(--color-background); 21 | } 22 | } 23 | 24 | @layer utilities{ 25 | .bg-default{ 26 | background-color: var(--color-background); 27 | } 28 | } -------------------------------------------------------------------------------- /nextjs/src/utils/http.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | const http = axios.create({ 4 | baseURL: process.env.NEXT_PUBLIC_NEST_HOST 5 | }) 6 | 7 | export default http; -------------------------------------------------------------------------------- /nextjs/src/utils/models.ts: -------------------------------------------------------------------------------- 1 | export interface TweetUser { 2 | Id: string; 3 | 4 | Name: string; 5 | 6 | ScreenName: string; 7 | 8 | Location: any; 9 | 10 | Description: string; 11 | 12 | ContributorsEnabled: boolean; 13 | 14 | ProfileImageURL: string; 15 | 16 | BiggerProfileImageURL: string; 17 | 18 | MiniProfileImageURL: string; 19 | 20 | OriginalProfileImageURL: string; 21 | 22 | ProfileImageURLHttps: string; 23 | 24 | BiggerProfileImageURLHttps: string; 25 | 26 | MiniProfileImageURLHttps: string; 27 | 28 | OriginalProfileImageURLHttps: string; 29 | 30 | DefaultProfileImage: boolean; 31 | 32 | URL: string; 33 | 34 | Protected: boolean; 35 | 36 | FollowersCount: number; 37 | 38 | ProfileBackgroundColor: string; 39 | 40 | ProfileTextColor: string; 41 | 42 | ProfileLinkColor: string; 43 | 44 | ProfileSidebarFillColor: string; 45 | 46 | ProfileSidebarBorderColor: string; 47 | 48 | ProfileUseBackgroundImage: boolean; 49 | 50 | DefaultProfile: boolean; 51 | 52 | ShowAllInlineMedia: boolean; 53 | 54 | FriendsCount: number; 55 | 56 | CreatedAt: number; 57 | 58 | FavouritesCount: number; 59 | 60 | UtcOffset: number; 61 | 62 | TimeZone: string; 63 | 64 | ProfileBackgroundImageURL: string; 65 | 66 | ProfileBackgroundImageUrlHttps: string; 67 | 68 | ProfileBannerURL: string; 69 | 70 | ProfileBannerRetinaURL: string; 71 | 72 | ProfileBannerIPadURL: string; 73 | 74 | ProfileBannerIPadRetinaURL: string; 75 | 76 | ProfileBannerMobileURL: string; 77 | 78 | ProfileBannerMobileRetinaURL: string; 79 | 80 | ProfileBackgroundTiled: boolean; 81 | 82 | Lang: string; 83 | 84 | StatusesCount: number; 85 | 86 | GeoEnabled: boolean; 87 | 88 | Verified: boolean; 89 | 90 | Translator: boolean; 91 | 92 | ListedCount: number; 93 | 94 | FollowRequestSent: boolean; 95 | 96 | WithheldInCountries: any[]; 97 | } 98 | 99 | export interface Tweet { 100 | Text: string; 101 | 102 | Source: string; 103 | 104 | Truncated: boolean; 105 | 106 | InReplyToStatusId: number; 107 | 108 | InReplyToUserId: number; 109 | 110 | InReplyToScreenName: string | null; 111 | 112 | GeoLocation: any; 113 | 114 | Place: any; 115 | 116 | Favorited: boolean; 117 | 118 | Retweeted: boolean; 119 | 120 | FavoriteCount: number; 121 | 122 | Retweet: false; 123 | 124 | Contributors: any[]; 125 | 126 | RetweetCount: number; 127 | 128 | RetweetedByMe: boolean; 129 | 130 | CurrentUserRetweetId: string; 131 | 132 | PossiblySensitive: boolean; 133 | 134 | Lang: string; 135 | 136 | WithheldInCountries: any[]; 137 | 138 | HashtagEntities: any[]; 139 | 140 | UserMentionEntities: any[]; 141 | 142 | MediaEntities: any[]; 143 | 144 | SymbolEntities: any[]; 145 | 146 | URLEntities: any[]; 147 | 148 | User: TweetUser; 149 | 150 | CreatedAt: number; 151 | } 152 | -------------------------------------------------------------------------------- /nextjs/src/utils/theme.ts: -------------------------------------------------------------------------------- 1 | export enum Themes { 2 | LIGHT = "light", 3 | DARK = "dark", 4 | } 5 | 6 | export function toggleTheme() { 7 | if (!localStorage.theme) { 8 | localStorage.theme = Themes.DARK; 9 | } else { 10 | localStorage.theme = 11 | localStorage.theme === Themes.DARK ? Themes.LIGHT : Themes.DARK; 12 | } 13 | loadTheme(); 14 | } 15 | 16 | export function loadTheme() { 17 | if (localStorage.theme === Themes.DARK || !("theme" in localStorage)) { 18 | document.documentElement.classList.add(Themes.DARK); 19 | } else { 20 | document.documentElement.classList.remove(Themes.DARK); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /nextjs/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | darkMode: 'class', 3 | content: [ 4 | "./src/pages/**/*.{js,ts,jsx,tsx}", 5 | "./src/components/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [], 11 | } 12 | -------------------------------------------------------------------------------- /nextjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "esModuleInterop": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "jsx": "preserve", 16 | "incremental": true 17 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /nextjs/utility-first.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | {# #} 23 | 24 | 25 | 26 | 27 | 28 | --------------------------------------------------------------------------------
31 | {tweet.User.Name} 32 | 33 | @{tweet.User.ScreenName} . {timeAgo.format(tweet.CreatedAt)} 34 | 35 |
{tweet.Text}
21 | Get started by editing{' '} 22 | pages/index.tsx 23 |
pages/index.tsx
Find in-depth information about Next.js features and API.
Learn about Next.js in an interactive course with quizzes!
Discover and deploy boilerplate example Next.js projects.
50 | Instantly deploy your Next.js site to a public URL with Vercel. 51 |