commit d14ed4be15f780a3f1b87f93805f34e214902d39 Author: Dominic Grimm Date: Sat Jan 8 13:29:22 2022 +0100 init diff --git a/.example.env b/.example.env new file mode 100644 index 0000000..588b219 --- /dev/null +++ b/.example.env @@ -0,0 +1,4 @@ +POSTGRES_USER= +POSTGRES_PASSWORD= + +BACKEND_JWT_SECRET= diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..aaa4958 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# mentorenwahl diff --git a/config/nginx/nginx.conf b/config/nginx/nginx.conf new file mode 100644 index 0000000..705f371 --- /dev/null +++ b/config/nginx/nginx.conf @@ -0,0 +1,20 @@ +events { +} + +http { + server { + # location / { + # # proxy_set_header Host $host; + # # proxy_set_header X-Real-IP $remote_addr; + # # proxy_pass http://frontend:3000; + # } + + location /graphql { + proxy_pass http://backend:8080; + } + + location /adminer { + proxy_pass http://adminer:8080; + } + } +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c4f70d0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,43 @@ +services: + nginx: + container_name: nginx + image: nginx:1.20.2-alpine + volumes: + - ./config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro + ports: + - 80:80 + depends_on: + - backend + + db: + image: postgres:alpine3.15 + container_name: db + env_file: .env + environment: + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - db:/var/lib/postgresql/data + + adminer: + image: adminer:4.8.1-standalone + container_name: adminer + depends_on: + - db + + backend: + build: + context: ./docker/backend + args: + BUILD_ENV: production + container_name: backend + environment: + BACKEND_SERVER_PORT: 8080 + BACKEND_SERVER_HOST: 0.0.0.0 + BACKEND_DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_USER} + BACKEND_JWT_SECRET: ${BACKEND_JWT_SECRET} + depends_on: + - db + +volumes: + db: diff --git a/docker/backend/.dockerignore b/docker/backend/.dockerignore new file mode 100644 index 0000000..7c3e445 --- /dev/null +++ b/docker/backend/.dockerignore @@ -0,0 +1,6 @@ +/docs/ +/lib/ +/bin/ +/.shards/ +*.dwarf +.ameba.yml diff --git a/docker/backend/.gitignore b/docker/backend/.gitignore new file mode 100644 index 0000000..7c3e445 --- /dev/null +++ b/docker/backend/.gitignore @@ -0,0 +1,6 @@ +/docs/ +/lib/ +/bin/ +/.shards/ +*.dwarf +.ameba.yml diff --git a/docker/backend/Dockerfile b/docker/backend/Dockerfile new file mode 100644 index 0000000..c2bd29e --- /dev/null +++ b/docker/backend/Dockerfile @@ -0,0 +1,44 @@ +FROM python:alpine3.15 as pgsanity +WORKDIR /app +RUN apk add libecpg-dev --no-cache +RUN pip3 install pgsanity +COPY ./db ./db +RUN find -name "*.sql" | xargs pgsanity + +FROM crystallang/crystal:1.2.2-alpine as micrate-deps +WORKDIR /app +COPY ./micrate/shard.yml ./micrate/shard.lock ./ +RUN shards install --production + +FROM crystallang/crystal:1.2.2-alpine as micrate-builder +ARG BUILD_ENV +WORKDIR /app +COPY --from=micrate-deps /app/shard.yml /app/shard.lock ./ +COPY --from=micrate-deps /app/lib lib/ +COPY ./micrate/src ./src +COPY ./scripts ./scripts +RUN . ./scripts/build.sh ${BUILD_ENV} + +FROM crystallang/crystal:1.2.2-alpine as deps +WORKDIR /app +RUN apk add curl --no-cache +COPY ./shard.yml ./shard.lock ./ +RUN shards install + +FROM crystallang/crystal:1.2.2-alpine as builder +ARG BUILD_ENV +WORKDIR /app +COPY --from=deps /app/shard.yml /app/shard.lock ./ +COPY --from=deps /app/lib ./lib +COPY --from=deps /app/bin ./bin +COPY ./src ./src +RUN if [ ${BUILD_ENV} = "development" ]; then ./bin/ameba ./src; fi +COPY ./scripts ./scripts +RUN . ./scripts/build.sh ${BUILD_ENV} + +FROM scratch as runner +COPY --from=micrate-builder /app/bin/micrate . +COPY --from=builder /app/bin/mw . +COPY --from=pgsanity /app/db ./db +EXPOSE 8080 +CMD [ "/mw" ] diff --git a/docker/backend/db/migrations/20211126143138_init.sql b/docker/backend/db/migrations/20211126143138_init.sql new file mode 100644 index 0000000..e18f7e3 --- /dev/null +++ b/docker/backend/db/migrations/20211126143138_init.sql @@ -0,0 +1,79 @@ +-- +micrate Up +-- SQL in section 'Up' is executed when this migration is applied +CREATE TYPE user_roles AS ENUM ('Admin', 'Teacher', 'Student'); + +CREATE TABLE users( + id BIGSERIAL PRIMARY KEY, + firstname TEXT NOT NULL, + lastname TEXT NOT NULL, + email TEXT NOT NULL, + PASSWORD TEXT NOT NULL, + role user_roles NOT NULL, + blocked BOOLEAN NOT NULL, + UNIQUE (firstname, lastname, email) +); + +CREATE TABLE admins( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL UNIQUE REFERENCES users(id) +); + +CREATE TABLE teachers( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL UNIQUE REFERENCES users(id), + max_students INT NOT NULL +); + +CREATE TABLE students( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL UNIQUE REFERENCES users(id), + skif BOOLEAN NOT NULL +); + +ALTER TABLE + users +ADD + COLUMN admin_id BIGINT UNIQUE REFERENCES admins(id); + +ALTER TABLE + users +ADD + COLUMN teacher_id BIGINT UNIQUE REFERENCES teachers(id); + +ALTER TABLE + users +ADD + COLUMN student_id BIGINT UNIQUE REFERENCES students(id); + +CREATE TABLE votes( + id BIGSERIAL PRIMARY KEY, + student_id BIGINT NOT NULL UNIQUE REFERENCES students(id) +); + +ALTER TABLE + students +ADD + COLUMN vote_id BIGINT UNIQUE REFERENCES votes(id); + +CREATE TABLE teacher_votes( + id BIGSERIAL PRIMARY KEY, + vote_id BIGINT NOT NULL REFERENCES votes(id), + teacher_id BIGINT NOT NULL REFERENCES teachers(id), + priority INT NOT NULL +); + +-- +micrate Down +-- SQL section 'Down' is executed when this migration is rolled back +DROP TABLE teacher_votes; + +DROP TABLE votes; + +DROP TABLE users; + +DROP TABLE admins; + +DROP TABLE teachers; + +DROP TABLE students; + +DROP TYPE user_roles; \ No newline at end of file diff --git a/docker/backend/micrate/.dockerignore b/docker/backend/micrate/.dockerignore new file mode 100644 index 0000000..0bb75ea --- /dev/null +++ b/docker/backend/micrate/.dockerignore @@ -0,0 +1,5 @@ +/docs/ +/lib/ +/bin/ +/.shards/ +*.dwarf diff --git a/docker/backend/micrate/.gitignore b/docker/backend/micrate/.gitignore new file mode 100644 index 0000000..0bb75ea --- /dev/null +++ b/docker/backend/micrate/.gitignore @@ -0,0 +1,5 @@ +/docs/ +/lib/ +/bin/ +/.shards/ +*.dwarf diff --git a/docker/backend/micrate/shard.lock b/docker/backend/micrate/shard.lock new file mode 100644 index 0000000..b3bd2d6 --- /dev/null +++ b/docker/backend/micrate/shard.lock @@ -0,0 +1,14 @@ +version: 2.0 +shards: + db: + git: https://github.com/crystal-lang/crystal-db.git + version: 0.10.1 + + micrate: + git: https://github.com/juanedi/micrate.git + version: 0.12.0 + + pg: + git: https://github.com/will/crystal-pg.git + version: 0.24.0 + diff --git a/docker/backend/micrate/shard.yml b/docker/backend/micrate/shard.yml new file mode 100644 index 0000000..686cff9 --- /dev/null +++ b/docker/backend/micrate/shard.yml @@ -0,0 +1,19 @@ +name: micrate +version: 0.1.0 + +authors: + - Dominic Grimm + +targets: + micrate: + main: src/micrate.cr + +crystal: 1.2.2 + +license: MIT + +dependencies: + micrate: + github: juanedi/micrate + pg: + github: will/crystal-pg diff --git a/docker/backend/micrate/src/micrate.cr b/docker/backend/micrate/src/micrate.cr new file mode 100755 index 0000000..1de4d7f --- /dev/null +++ b/docker/backend/micrate/src/micrate.cr @@ -0,0 +1,5 @@ +require "micrate" +require "pg" + +Micrate::DB.connection_url = ENV["BACKEND_DATABASE_URL"]? +Micrate::Cli.run diff --git a/docker/backend/scripts/build.sh b/docker/backend/scripts/build.sh new file mode 100644 index 0000000..7cc2140 --- /dev/null +++ b/docker/backend/scripts/build.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env sh + +BASE_FLAGS="--production --static --verbose -s -p -t" +DEV_FLAGS="$BASE_FLAGS" +PROD_FLAGS="--release --no-debug $BASE_FLAGS" + +echo "Building targets in '$1' mode..." +if [ "$1" = "development" ]; then + # shellcheck disable=SC2086 + time shards build $DEV_FLAGS +else + # shellcheck disable=SC2086 + time shards build $PROD_FLAGS +fi diff --git a/docker/backend/shard.lock b/docker/backend/shard.lock new file mode 100644 index 0000000..6f063fb --- /dev/null +++ b/docker/backend/shard.lock @@ -0,0 +1,66 @@ +version: 2.0 +shards: + CrystalEmail: + git: https://git.sceptique.eu/Sceptique/CrystalEmail + version: 0.2.6+git.commit.f217992c51048b3f94f4e064cd6c5123e32a1e27 + + ameba: + git: https://github.com/crystal-ameba/ameba.git + version: 0.14.3 + + bindata: + git: https://github.com/spider-gazelle/bindata.git + version: 1.9.1 + + commander: + git: https://github.com/mrrooijen/commander.git + version: 0.4.0 + + compiled_license: + git: https://github.com/grimmigerfuchs/compiled_license.git + version: 2.0.0 + + crystal-argon2: + git: https://github.com/axentro/crystal-argon2.git + version: 0.1.3 + + db: + git: https://github.com/crystal-lang/crystal-db.git + version: 0.10.1 + + granite: + git: https://github.com/amberframework/granite.git + version: 0.23.0 + + graphql: + git: https://github.com/graphql-crystal/graphql.git + version: 0.3.2+git.commit.8c6dc73c0c898ca511d9d12efefca7c837c25946 + + jwt: + git: https://github.com/crystal-community/jwt.git + version: 1.6.0 + + openssl_ext: + git: https://github.com/spider-gazelle/openssl_ext.git + version: 2.1.5 + + pg: + git: https://github.com/will/crystal-pg.git + version: 0.24.0 + + pretty: + git: https://github.com/maiha/pretty.cr.git + version: 1.1.1 + + seg: + git: https://github.com/soveran/seg.git + version: 0.1.0+git.commit.b404c986b5a894830878cd6b296df53ef34d9cfa + + shard: + git: https://github.com/maiha/shard.cr.git + version: 0.3.1 + + toro: + git: https://github.com/soveran/toro.git + version: 0.4.2+git.commit.d2103dddcc9cc757e6b82613e040b1d50663a2e6 + diff --git a/docker/backend/shard.yml b/docker/backend/shard.yml new file mode 100644 index 0000000..db64949 --- /dev/null +++ b/docker/backend/shard.yml @@ -0,0 +1,40 @@ +name: mw +version: 0.1.0 + +authors: + - Dominic Grimm + +targets: + mw: + main: src/app.cr + +crystal: 1.2.2 + +dependencies: + granite: + github: amberframework/granite + pg: + github: will/crystal-pg + crystal-argon2: + github: Axentro/crystal-argon2 + graphql: + github: graphql-crystal/graphql + branch: master + jwt: + github: crystal-community/jwt + CrystalEmail: + git: https://git.sceptique.eu/Sceptique/CrystalEmail + branch: master + shard: + github: maiha/shard.cr + toro: + github: soveran/toro + branch: master + commander: + github: mrrooijen/commander + compiled_license: + github: grimmigerFuchs/compiled_license + +development_dependencies: + ameba: + github: crystal-ameba/ameba diff --git a/docker/backend/src/app.cr b/docker/backend/src/app.cr new file mode 100644 index 0000000..49d6c90 --- /dev/null +++ b/docker/backend/src/app.cr @@ -0,0 +1,94 @@ +require "commander" +require "./mw.cr" + +def input(prompt : String) : String + print prompt + (gets || "").chomp.strip +end + +cli = Commander::Command.new do |cmd| + cmd.use = "mw" + cmd.long = "Mentorenwahl" + + cmd.run do + MW.run + end + + cmd.commands.add do |c| + c.use = "version" + c.long = "Prints the current version" + + c.run do + puts MW::VERSION + end + end + + cmd.commands.add do |c| + c.use = "authors" + c.long = "Prints the authors" + + c.run do + puts MW::AUTHORS.join(",\n") + end + end + + cmd.commands.add do |c| + c.use = "licenses" + c.long = "Prints the licenses of libraries used" + + c.run do + puts MW::LICENSES + end + end + + cmd.commands.add do |c| + c.use = "seed" + c.long = "Seeds the database with required data" + + c.run do + puts "Seeding database with admin user..." + # firstname = input "Firstname: " + # lastname = input "Lastname: " + # email = input "Email: " + # password = input "Password: " + # password_confirmation = input "Password confirmation: " + data = { + "firstname" => input("Firstname: "), + "lastname" => input("Lastname: "), + "email" => input("Email: "), + "password" => MW::Auth.hash_password(input("Password: ")), + "role" => MW::Db::UserRole::Admin.to_s, + } + password_confirmation = input("Password confirmation: ") + + if data.values.any?(&.empty?) + abort "Values can't be empty!" + elsif !MW::Auth.verify_password?(password_confirmation, data["password"]) + abort "Passwords do not match!" + end + + puts "---" + data.each { |k, v| puts "#{k.capitalize}: #{v}" } + puts "---" + + unless input("Are you sure? (y/n) ") == "y" + abort "Aborted!" + end + + puts "Seeding database with admin user..." + + user = MW::Db::User.create!(data) + admin = MW::Db::Admin.create!(user_id: user.id) + + puts "Done!" + + puts "---" + puts "User id: #{user.id}" + puts "Admin id: #{admin.id}" + puts "Token: #{MW::Auth.create_user_jwt(user_id: user.id.not_nil!)}" + puts "---" + end + end +end + +Commander.run(cli, ARGV) diff --git a/docker/backend/src/mw.cr b/docker/backend/src/mw.cr new file mode 100644 index 0000000..318bfb4 --- /dev/null +++ b/docker/backend/src/mw.cr @@ -0,0 +1 @@ +require "./mw/*" diff --git a/docker/backend/src/mw/auth.cr b/docker/backend/src/mw/auth.cr new file mode 100644 index 0000000..5da55e4 --- /dev/null +++ b/docker/backend/src/mw/auth.cr @@ -0,0 +1,43 @@ +require "crystal-argon2" +require "jwt" + +module MW + module Auth + extend self + + BEARER = "Bearer " + + def hash_password(password : String) : String + Argon2::Password.create(password) + end + + def verify_password?(password : String, hash : String) : Bool + !!Argon2::Password.verify_password(password, hash) + rescue + false + end + + private def create_jwt(data, expiration : Int) : String + payload = { + "data" => data.to_h, + "exp" => expiration, + } + + JWT.encode(payload.to_h, ENV_REQUESTER["BACKEND_JWT_SECRET"], JWT::Algorithm::HS256) + end + + def create_user_jwt(user_id : Int, expiration : Int = (Time.utc + Time::Span.new(days: 1)).to_unix) : String + create_jwt({user_id: user_id}, expiration) + end + + def decode_jwt(jwt : String) : JSON::Any + JWT.decode(jwt, ENV_REQUESTER["BACKEND_JWT_SECRET"], JWT::Algorithm::HS256)[0] + end + + def decode_jwt?(jwt : String) : JSON::Any? + decode_jwt(jwt) + rescue + nil + end + end +end diff --git a/docker/backend/src/mw/authors.cr b/docker/backend/src/mw/authors.cr new file mode 100644 index 0000000..7878853 --- /dev/null +++ b/docker/backend/src/mw/authors.cr @@ -0,0 +1,5 @@ +require "shard" + +module MW + AUTHORS = Shard.authors +end diff --git a/docker/backend/src/mw/context.cr b/docker/backend/src/mw/context.cr new file mode 100644 index 0000000..e8c80a9 --- /dev/null +++ b/docker/backend/src/mw/context.cr @@ -0,0 +1,88 @@ +require "http/request" +require "graphql" +require "granite" + +module MW + class Context < GraphQL::Context + getter user : Db::User? + getter role : Schema::UserRole? + getter external : (Db::Admin | Db::Teacher | Db::Student)? + + # ameba:disable Metrics/CyclomaticComplexity + def initialize(request : HTTP::Request, *rest) + super(*rest) + + token = request.headers["Authorization"]? + if token && token[..Auth::BEARER.size - 1] == Auth::BEARER + payload = Auth.decode_jwt?(token[Auth::BEARER.size..]) + return unless payload + + data = payload["data"].as_h + @user = Db::User.find(data["user_id"].as_i) + return if @user.nil? || @user.not_nil!.blocked + + if @user + tmp_role = Schema::UserRole.parse?(@user.as(Db::User).role).not_nil! + if tmp_role + @external = + case Schema::UserRole.parse?(@user.not_nil!.role) + when Schema::UserRole::Admin + @user.not_nil!.admin + when Schema::UserRole::Teacher + @user.not_nil!.teacher + when Schema::UserRole::Student + @user.not_nil!.student + end + @role = tmp_role if @external + end + end + end + end + + def authenticated? : Bool + !(@role.nil? && @external.nil?) + end + + def authenticated! : Bool + raise "Not authenticated" unless authenticated? + + true + end + + def role?(role : Schema::UserRole) : Bool + @role == role == case @external + when Db::Admin + Schema::UserRole::Admin + when Db::Teacher + Schema::UserRole::Teacher + when Db::Student + Schema::UserRole::Student + end + end + + def role!(role : Schema::UserRole) : Bool + raise "Invalid permissions" unless role? role + + true + end + + def admin? : Bool + role? Schema::UserRole::Admin + end + + def admin! : Bool + role! Schema::UserRole::Admin + end + + def self.db_eq_role?(external : Granite::Base, role : Schema::UserRole) : Bool + role == case external + when Db::Admin + Schema::UserRole::Admin + when Db::Teacher + Schema::UserRole::Teacher + when Db::Student + Schema::UserRole::Student + end + end + end +end diff --git a/docker/backend/src/mw/db.cr b/docker/backend/src/mw/db.cr new file mode 100644 index 0000000..9d9eecd --- /dev/null +++ b/docker/backend/src/mw/db.cr @@ -0,0 +1,10 @@ +require "granite" +require "granite/adapter/pg" + +require "./db/*" + +module MW + module Db + Granite::Connections << Granite::Adapter::Pg.new(name: "pg", url: ENV_REQUESTER["BACKEND_DATABASE_URL"]) + end +end diff --git a/docker/backend/src/mw/db/admin.cr b/docker/backend/src/mw/db/admin.cr new file mode 100644 index 0000000..f158866 --- /dev/null +++ b/docker/backend/src/mw/db/admin.cr @@ -0,0 +1,13 @@ +require "granite" + +module MW + module Db + class Admin < Granite::Base + table admins + + belongs_to :user + + column id : Int64, primary: true + end + end +end diff --git a/docker/backend/src/mw/db/student.cr b/docker/backend/src/mw/db/student.cr new file mode 100644 index 0000000..5415887 --- /dev/null +++ b/docker/backend/src/mw/db/student.cr @@ -0,0 +1,15 @@ +require "granite" + +module MW + module Db + class Student < Granite::Base + table students + + belongs_to :user + has_one :vote + + column id : Int64, primary: true + column skif : Bool + end + end +end diff --git a/docker/backend/src/mw/db/teacher.cr b/docker/backend/src/mw/db/teacher.cr new file mode 100644 index 0000000..d1f3fe1 --- /dev/null +++ b/docker/backend/src/mw/db/teacher.cr @@ -0,0 +1,15 @@ +require "granite" + +module MW + module Db + class Teacher < Granite::Base + table teachers + + belongs_to :user + has_many teacher_votes : TeacherVote + + column id : Int64, primary: true + column max_students : Int32 + end + end +end diff --git a/docker/backend/src/mw/db/teacher_vote.cr b/docker/backend/src/mw/db/teacher_vote.cr new file mode 100644 index 0000000..e6e8c6c --- /dev/null +++ b/docker/backend/src/mw/db/teacher_vote.cr @@ -0,0 +1,31 @@ +require "granite" + +module MW + module Db + class TeacherVote < Granite::Base + table teacher_votes + + belongs_to :vote + belongs_to :teacher + + column id : Int64, primary: true + column priority : Int32 + + validate :teacher, "must be present" do |teacher_vote| + !teacher_vote.teacher.nil? + end + + validate :teacher, "must be student unique" do |teacher_vote| + self.where(vote_id: teacher_vote.vote.id, teacher_id: teacher_vote.teacher.not_nil!.id).count == 0 + end + + validate :priority, "must be greater than 0" do |teacher_vote| + teacher_vote.priority > 0 + end + + validate :priority, "must be less than the number of teachers" do |teacher_vote| + teacher_vote.priority < Teacher.count + end + end + end +end diff --git a/docker/backend/src/mw/db/user.cr b/docker/backend/src/mw/db/user.cr new file mode 100644 index 0000000..06c53fa --- /dev/null +++ b/docker/backend/src/mw/db/user.cr @@ -0,0 +1,47 @@ +require "CrystalEmail" +require "granite" + +module MW + module Db + class User < Granite::Base + table users + + has_one :admin + has_one :teacher + has_one :student + + column id : Int64, primary: true + column firstname : String + column lastname : String + column email : String + column password : String + column role : String + column blocked : Bool = false + + validate :email, "needs to be an email address" do |user| + CrystalEmail::Rfc5322::Public.validates?(user.email) + end + + validate :role, "needs to be a valid role" do |user| + UserRole.parse?(user.role).in?(UserRole.values) + end + + validate :role, "user external needs to be a valid role" do |user| + if user.admin.nil? && user.teacher.nil? && user.student.nil? + true + else + !!case UserRole.parse(user.role) + when UserRole::Admin + user.admin && user.teacher.nil? && user.student.nil? + when UserRole::Teacher + user.admin.nil? && user.teacher && user.student.nil? + when UserRole::Student + user.admin.nil? && user.teacher.nil? && user.student + else + false + end + end + end + end + end +end diff --git a/docker/backend/src/mw/db/user_role.cr b/docker/backend/src/mw/db/user_role.cr new file mode 100644 index 0000000..c0f3843 --- /dev/null +++ b/docker/backend/src/mw/db/user_role.cr @@ -0,0 +1,9 @@ +module MW + module Db + enum UserRole + Admin + Teacher + Student + end + end +end diff --git a/docker/backend/src/mw/db/vote.cr b/docker/backend/src/mw/db/vote.cr new file mode 100644 index 0000000..a342ec8 --- /dev/null +++ b/docker/backend/src/mw/db/vote.cr @@ -0,0 +1,14 @@ +require "granite" + +module MW + module Db + class Vote < Granite::Base + table votes + + belongs_to :student + has_many teacher_votes : TeacherVote + + column id : Int64, primary: true + end + end +end diff --git a/docker/backend/src/mw/env_requester.cr b/docker/backend/src/mw/env_requester.cr new file mode 100644 index 0000000..e9def66 --- /dev/null +++ b/docker/backend/src/mw/env_requester.cr @@ -0,0 +1,43 @@ +module MW + class EnvRequester + private property keys + + def initialize(@keys = {} of String => String?) + end + + def initialize(keys : Array(String)) + @keys = {} of String => String? + keys.each { |k| self.<< k } + end + + def <<(key : String) : self + @keys[key] = ENV[key]? + + self + end + + def []?(key : String) : String? + if @keys.has_key?(key) + @keys[key]? + end + end + + def [](key : String) : String + if @keys.has_key?(key) + val = @keys[key]? + raise "ENV[#{key}] is nil" unless val + + val + else + raise "No such key: #{key}" + end + end + end + + ENV_REQUESTER = EnvRequester.new([ + "BACKEND_DATABASE_URL", + "BACKEND_ADMIN_EMAIL", + "BACKEND_ADMIN_PASSWORD", + "BACKEND_JWT_SECRET", + ]) +end diff --git a/docker/backend/src/mw/licenses.cr b/docker/backend/src/mw/licenses.cr new file mode 100644 index 0000000..523196d --- /dev/null +++ b/docker/backend/src/mw/licenses.cr @@ -0,0 +1,5 @@ +require "compiled_license" + +module MW + LICENSES = CompiledLicense::LICENSES +end diff --git a/docker/backend/src/mw/run.cr b/docker/backend/src/mw/run.cr new file mode 100644 index 0000000..193d6f9 --- /dev/null +++ b/docker/backend/src/mw/run.cr @@ -0,0 +1,13 @@ +require "http/server" + +module MW + extend self + + def run : Nil + Server.run(8080, [HTTP::LogHandler.new, HTTP::ErrorHandler.new]) do |server| + address = server.bind_tcp("0.0.0.0", 8080, true) + puts "Listening on http://#{address}" + server.listen + end + end +end diff --git a/docker/backend/src/mw/schema.cr b/docker/backend/src/mw/schema.cr new file mode 100644 index 0000000..e30cf6c --- /dev/null +++ b/docker/backend/src/mw/schema.cr @@ -0,0 +1,10 @@ +require "graphql" + +require "./schema/helpers" +require "./schema/*" + +module MW + module Schema + SCHEMA = GraphQL::Schema.new(Query.new, Mutation.new) + end +end diff --git a/docker/backend/src/mw/schema/admin.cr b/docker/backend/src/mw/schema/admin.cr new file mode 100644 index 0000000..68a9bcf --- /dev/null +++ b/docker/backend/src/mw/schema/admin.cr @@ -0,0 +1,26 @@ +require "graphql" + +module MW + module Schema + @[GraphQL::Object] + class Admin < GraphQL::BaseObject + include Helpers::DbObject + + db_object Db::Admin + + @[GraphQL::Field] + def user : User + User.new(find!.user) + end + end + + @[GraphQL::InputObject] + class AdminCreateInput < GraphQL::BaseInputObject + getter user_id + + @[GraphQL::Field] + def initialize(@user_id : Int32) + end + end + end +end diff --git a/docker/backend/src/mw/schema/helpers.cr b/docker/backend/src/mw/schema/helpers.cr new file mode 100644 index 0000000..3cddcb5 --- /dev/null +++ b/docker/backend/src/mw/schema/helpers.cr @@ -0,0 +1,65 @@ +require "graphql" + +module MW + module Schema + module Helpers + module ObjectMacros + macro field(type) + property {{ type.var }} {% if type.value %} = {{ type.value }}{% end %} + + @[GraphQL::Field] + def {{ type.var }} : {{ type.type }} + @{{ type.var }} + end + end + end + + module ObjectDbInit + macro db_init(type) + def initialize(obj : {{ type }}) + initialize(obj.id.not_nil!) + end + end + end + + module ObjectFinders + macro finders(type) + def find : {{ type }}? + {{ type }}.find(@id) + end + + def find! : {{ type }} + obj = find + raise "#{{{ type }}} not found" unless obj + + obj + end + end + end + + module DbObject + macro db_object(type) + include ::MW::Schema::Helpers::ObjectDbInit + include ::MW::Schema::Helpers::ObjectFinders + + db_init {{ type }} + finders {{ type }} + + property id + + def initialize(@id : Int32) + end + + def initialize(obj : {{ type }}) + @id = obj.id.not_nil!.to_i + end + + @[GraphQL::Field] + def id : Int32 + @id + end + end + end + end + end +end diff --git a/docker/backend/src/mw/schema/mutation.cr b/docker/backend/src/mw/schema/mutation.cr new file mode 100644 index 0000000..9d606a5 --- /dev/null +++ b/docker/backend/src/mw/schema/mutation.cr @@ -0,0 +1,136 @@ +require "graphql" + +module MW + module Schema + @[GraphQL::Object] + class Mutation < GraphQL::BaseMutation + @[GraphQL::Field] + def login(input : LoginInput) : LoginPayload + user = Db::User.find_by(email: input.email) + raise "Auth failed" unless user && Auth.verify_password?(input.password, user.password) + + LoginPayload.new( + user: User.new(user), + token: Auth.create_user_jwt(user.id.not_nil!.to_i), + ) + end + + @[GraphQL::Field] + def create_user(context : Context, input : UserCreateInput) : User + context.admin! + + user = Db::User.create!( + firstname: input.firstname, + lastname: input.lastname, + email: input.email, + password: Auth.hash_password(input.password), + role: input.role.to_s, + blocked: input.blocked, + ) + if input.role + case input.role + when UserRole::Teacher + user.teacher = Db::Teacher.create!(user_id: user.id, max_students: input.teacher.not_nil!.max_students) + when UserRole::Student + user.student = Db::Student.create!(user_id: user.id, skif: input.student.not_nil!.skif) + end + user.save! + end + + User.new(user) + end + + @[GraphQL::Field] + def delete_user(context : Context, id : Int32) : Int32 + context.admin! + + user = Db::User.find!(id) + user.destroy! + + id + end + + @[GraphQL::Field] + def create_admin(context : Context, input : AdminCreateInput) : Admin + context.admin! + + admin = Db::Admin.create!(user_id: input.user_id) + Admin.new(admin) + end + + @[GraphQL::Field] + def delete_admin(context : Context, id : Int32) : Int32 + context.admin! + + admin = Db::Admin.find!(id) + admin.destroy! + + id + end + + @[GraphQL::Field] + def create_teacher(context : Context, input : TeacherCreateInput) : Teacher + context.admin! + + teacher = Db::Teacher.create!(user_id: input.user_id, max_students: input.max_students) + Teacher.new(teacher) + end + + @[GraphQL::Field] + def delete_teacher(context : Context, id : Int32) : Int32 + context.admin! + + teacher = Db::Teacher.find!(id) + teacher.destroy! + + id + end + + @[GraphQL::Field] + def create_student(context : Context, input : StudentCreateInput) : Student + context.admin! + + user = Db::User.find!(input.user_id) + raise "User not a student" unless UserRole.parse(user.role) == UserRole::Student + + student = Db::Student.create!(user_id: user.id) + Student.new(student) + end + + @[GraphQL::Field] + def delete_student(context : Context, id : Int32) : Int32 + context.admin! + + student = Db::Student.find!(id) + student.destroy! + + id + end + + @[GraphQL::Field] + def create_vote(context : Context, input : VoteCreateInput) : Vote + # context.admin! + + # student = Db::Student.find!(input.student_id) + # # student.vote = Db::Vote.new(student_id: student.id) + # # student.save! + # pp! Db::Vote.create!(student_id: student.id.not_nil!) + # pp! student + # pp! student.vote + # input.teacher_ids.not_nil!.each_with_index do |t_id, i| + # Db::TeacherVote.create!(vote_id: student.vote.not_nil!.id.not_nil!, teacher_id: t_id, priority: i) + # end if input.teacher_ids + # pp! student.vote.not_nil!.teacher_votes.to_a + + # Vote.new(student.vote.not_nil!) + + context.role! UserRole::Student + + student = context.external.not_nil!.as(Db::Student) + vote = Db::Vote.create!(student_id: student.id) + + Vote.new(vote) + end + end + end +end diff --git a/docker/backend/src/mw/schema/query.cr b/docker/backend/src/mw/schema/query.cr new file mode 100644 index 0000000..0396a2d --- /dev/null +++ b/docker/backend/src/mw/schema/query.cr @@ -0,0 +1,87 @@ +require "graphql" + +module MW + module Schema + @[GraphQL::Object] + class Query < GraphQL::BaseQuery + @[GraphQL::Field] + def ok : Bool + true + end + + @[GraphQL::Field] + def me(context : Context) : User + context.authenticated! + + User.new(context.user.not_nil!) + end + + @[GraphQL::Field] + def user(context : Context, id : Int32) : User + context.admin! + + User.new(id) + end + + @[GraphQL::Field({UserRole::Admin})] + def users(context : Context) : Array(User) + puts "AUTHORIZED ALLOWED ROLES: #{{{ @def.annotation(GraphQL::Field)[0] }}}" + context.admin! + + Db::User.all.map { |user| User.new(user) } + end + + @[GraphQL::Field] + def admin(context : Context, id : Int32) : Admin + context.admin! + + Admin.new(Db::Admin.find!(id)) + end + + @[GraphQL::Field] + def admins(context : Context) : Array(Admin) + context.admin! + + Db::Admin.all.map { |admin| Admin.new(admin) } + end + + @[GraphQL::Field] + def teacher(id : Int32) : Teacher + Teacher.new(Db::Teacher.find!(id)) + end + + @[GraphQL::Field] + def teachers : Array(Teacher) + Db::Teacher.all.map { |teacher| Teacher.new(teacher) } + end + + @[GraphQL::Field] + def student(context : Context, id : Int32) : Student + context.admin! + + Student.new(Db::Student.find!(id)) + end + + @[GraphQL::Field] + def students(context : Context) : Array(Student) + context.admin! + + Db::Student.all.map { |student| Student.new(student) } + end + + @[GraphQL::Field] + def vote(context : Context, id : Int32) : Vote + context.admin! + + Vote.new(Db::Vote.find!(id)) + end + + @[GraphQL::Field] + def votes(context : Context) : Array(Vote) + context.admin! + + Db::Vote.all.map { |vote| Vote.new(vote) } + end + end + end +end diff --git a/docker/backend/src/mw/schema/student.cr b/docker/backend/src/mw/schema/student.cr new file mode 100644 index 0000000..41dfaa4 --- /dev/null +++ b/docker/backend/src/mw/schema/student.cr @@ -0,0 +1,48 @@ +require "graphql" + +module MW + module Schema + @[GraphQL::Object] + class Student < GraphQL::BaseObject + include Helpers::DbObject + + db_object Db::Student + + @[GraphQL::Field] + def user : User + User.new(find!.user) + end + + @[GraphQL::Field] + def skif : Bool + find!.skif + end + + @[GraphQL::Field] + def vote : Vote? + vote = find!.vote + + Vote.new(vote) if vote + end + end + + @[GraphQL::InputObject] + class StudentInput < GraphQL::BaseInputObject + getter skif + + @[GraphQL::Field] + def initialize(@skif : Bool) + end + end + + @[GraphQL::InputObject] + class StudentCreateInput < StudentInput + getter user_id + + @[GraphQL::Field] + def initialize(@user_id : Int32, skif : Bool) + super(skif) + end + end + end +end diff --git a/docker/backend/src/mw/schema/teacher.cr b/docker/backend/src/mw/schema/teacher.cr new file mode 100644 index 0000000..6393c9a --- /dev/null +++ b/docker/backend/src/mw/schema/teacher.cr @@ -0,0 +1,43 @@ +require "graphql" + +module MW + module Schema + @[GraphQL::Object] + class Teacher < GraphQL::BaseObject + include Helpers::DbObject + + db_object Db::Teacher + + @[GraphQL::Field] + def user : User + User.new(find!.user) + end + + @[GraphQL::Field] + def max_students(context : Context) : Int32 + context.admin! + + find!.max_students + end + end + + @[GraphQL::InputObject] + class TeacherInput < GraphQL::BaseInputObject + getter max_students + + @[GraphQL::Field] + def initialize(@max_students : Int32) + end + end + + @[GraphQL::InputObject] + class TeacherCreateInput < TeacherInput + getter user_id + + @[GraphQL::Field] + def initialize(@user_id : Int32, max_students : Int32) + super(max_students) + end + end + end +end diff --git a/docker/backend/src/mw/schema/teacher_vote.cr b/docker/backend/src/mw/schema/teacher_vote.cr new file mode 100644 index 0000000..fcd5f78 --- /dev/null +++ b/docker/backend/src/mw/schema/teacher_vote.cr @@ -0,0 +1,33 @@ +require "graphql" + +module MW + module Schema + @[GraphQL::Object] + class TeacherVote < GraphQL::BaseObject + include Helpers::DbObject + + db_object Db::TeacherVote + + @[GraphQL::Field] + def teacher : Teacher + Teacher.new(find!.teacher.not_nil!) + end + + @[GraphQL::Field] + def priority : Int32 + find!.priority + end + end + + @[GraphQL::InputObject] + class TeacherVoteCreateInput < GraphQL::BaseInputObject + getter vote_id + getter teacher_id + getter priority + + @[GraphQL::Field] + def initialize(@vote_id : Int32, @teacher_id : Int32, @priority : Int32) + end + end + end +end diff --git a/docker/backend/src/mw/schema/user.cr b/docker/backend/src/mw/schema/user.cr new file mode 100644 index 0000000..ff63c1c --- /dev/null +++ b/docker/backend/src/mw/schema/user.cr @@ -0,0 +1,157 @@ +require "graphql" + +module MW + module Schema + @[GraphQL::Enum] + enum UserRole + Admin + Teacher + Student + end + + @[GraphQL::Object] + class User < GraphQL::BaseObject + include Helpers::DbObject + + db_object Db::User + + @[GraphQL::Field] + def firstname : String + find!.firstname + end + + @[GraphQL::Field] + def lastname : String + find!.lastname + end + + @[GraphQL::Field] + def email : String + find!.email + end + + @[GraphQL::Field] + def role : UserRole + role = Db::UserRole.parse(find!.role) + case role + when Db::UserRole::Admin + UserRole::Admin + when Db::UserRole::Teacher + UserRole::Teacher + when Db::UserRole::Student + UserRole::Student + else + raise "Unknown role: #{role}" + end + end + + @[GraphQL::Field] + def external_id : Int32? + case Db::UserRole.parse(find!.role) + when Db::UserRole::Admin + find!.admin + when Db::UserRole::Teacher + find!.teacher + when Db::UserRole::Student + find!.student + end.not_nil!.id.not_nil!.to_i + rescue NilAssertionError + nil + end + + @[GraphQL::Field] + def admin : Admin? + admin = find!.admin + if admin + Admin.new(admin) + end + end + + @[GraphQL::Field] + def teacher : Teacher? + teacher = find!.teacher + if teacher + Teacher.new(teacher) + end + end + + @[GraphQL::Field] + def student : Student? + student = find!.student + if student + Student.new(student) + end + end + + @[GraphQL::Field] + def blocked : Bool + find!.blocked + end + end + + @[GraphQL::InputObject] + class UserCreateInput < GraphQL::BaseInputObject + getter firstname + getter lastname + getter email + getter password + getter role + getter teacher + getter student + getter blocked + + @[GraphQL::Field] + def initialize( + @firstname : String, + @lastname : String, + @email : String, + @password : String, + @role : UserRole, + @teacher : TeacherInput? = nil, + @student : StudentInput? = nil, + @blocked : Bool = false + ) + end + end + + @[GraphQL::InputObject] + class LoginInput < GraphQL::BaseInputObject + getter email + getter password + + @[GraphQL::Field] + def initialize( + @email : String, + @password : String + ) + end + end + + @[GraphQL::Object] + class LoginPayload < GraphQL::BaseObject + property user + property token + + def initialize( + @user : User, + @token : String + ) + end + + @[GraphQL::Field] + def user : User + @user + end + + @[GraphQL::Field] + def token : String + @token + end + + @[GraphQL::Field] + def bearer : String + Auth::BEARER + @token + end + end + end +end diff --git a/docker/backend/src/mw/schema/vote.cr b/docker/backend/src/mw/schema/vote.cr new file mode 100644 index 0000000..b46b671 --- /dev/null +++ b/docker/backend/src/mw/schema/vote.cr @@ -0,0 +1,31 @@ +require "graphql" + +module MW + module Schema + @[GraphQL::Object] + class Vote < GraphQL::BaseObject + include Helpers::DbObject + + db_object Db::Vote + + @[GraphQL::Field] + def student : Student + Student.new(find!.student) + end + + @[GraphQL::Field] + def teacher_votes : Array(TeacherVote) + find!.teacher_votes.map { |tv| TeacherVote.new(tv) } + end + end + + @[GraphQL::InputObject] + class VoteCreateInput < GraphQL::BaseInputObject + getter teacher_ids + + @[GraphQL::Field] + def initialize(@teacher_ids : Array(String)) + end + end + end +end diff --git a/docker/backend/src/mw/server.cr b/docker/backend/src/mw/server.cr new file mode 100644 index 0000000..e482e61 --- /dev/null +++ b/docker/backend/src/mw/server.cr @@ -0,0 +1,31 @@ +require "toro" +require "json" + +module MW + class Server < Toro::Router + private struct GraphQLData + include JSON::Serializable + + property query : String + property variables : Hash(String, JSON::Any)? + property operation_name : String? + end + + def routes + on "graphql" do + post do + content_type "application/json" + + data = GraphQLData.from_json(context.request.body.not_nil!.gets.not_nil!) + + write Schema::SCHEMA.execute( + data.query, + data.variables, + data.operation_name, + Context.new(context.request) + ) + end + end + end + end +end diff --git a/docker/backend/src/mw/version.cr b/docker/backend/src/mw/version.cr new file mode 100644 index 0000000..c489cfe --- /dev/null +++ b/docker/backend/src/mw/version.cr @@ -0,0 +1,5 @@ +require "shard" + +module MW + VERSION = Shard.version +end diff --git a/docker/backend_old/.dockerignore b/docker/backend_old/.dockerignore new file mode 100644 index 0000000..b30ae47 --- /dev/null +++ b/docker/backend_old/.dockerignore @@ -0,0 +1,129 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +.prettierrc diff --git a/docker/backend_old/.gitignore b/docker/backend_old/.gitignore new file mode 100644 index 0000000..20b0c92 --- /dev/null +++ b/docker/backend_old/.gitignore @@ -0,0 +1,127 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/docker/backend_old/.prettierrc b/docker/backend_old/.prettierrc new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/docker/backend_old/.prettierrc @@ -0,0 +1 @@ +{} diff --git a/docker/backend_old/Dockerfile b/docker/backend_old/Dockerfile new file mode 100644 index 0000000..8c74c4a --- /dev/null +++ b/docker/backend_old/Dockerfile @@ -0,0 +1,23 @@ +FROM node:17-alpine3.12 as deps +WORKDIR /app +COPY ./package.json ./yarn.lock ./ +RUN yarn --frozen-lockfile + +FROM node:17-alpine3.12 as builder +WORKDIR /app +COPY --from=deps /app/package.json /app/yarn.lock ./ +COPY --from=deps /app/node_modules ./node_modules +COPY ./prisma ./prisma +RUN npx prisma generate +COPY . . +RUN yarn build +RUN npm prune --production + +FROM node:17-alpine3.12 as runner +WORKDIR /app +COPY --from=builder /app/package.json . +COPY --from=builder /app/node_modules ./node_modules +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/prisma ./prisma +EXPOSE 8080 +CMD ["yarn", "start"] diff --git a/docker/backend_old/package.json b/docker/backend_old/package.json new file mode 100644 index 0000000..f4268b1 --- /dev/null +++ b/docker/backend_old/package.json @@ -0,0 +1,28 @@ +{ + "name": "backend", + "version": "1.0.0", + "private": true, + "main": "dist/index.js", + "license": "MIT", + "scripts": { + "start": "node --trace-warnings --enable-source-maps dist/index.js", + "build": "rm -rf dist/ && tsc" + }, + "devDependencies": { + "@types/node": "^17.0.5", + "typescript": "^4.5.4" + }, + "dependencies": { + "@envelop/apollo-server-errors": "^1.2.1", + "@envelop/graphql-jit": "^1.3.1", + "@envelop/resource-limitations": "^0.4.1", + "@prisma/client": "^3.7.0", + "argon2": "^0.28.3", + "graphql": "15", + "graphql-scalars": "^1.14.1", + "graphql-yoga": "^2.0.0-alpha.6", + "nexus": "^1.1.0", + "nexus-prisma": "^0.35.0", + "prisma": "^3.7.0" + } +} diff --git a/docker/backend_old/prisma/schema.prisma b/docker/backend_old/prisma/schema.prisma new file mode 100644 index 0000000..cff53c1 --- /dev/null +++ b/docker/backend_old/prisma/schema.prisma @@ -0,0 +1,47 @@ +// This is your Prisma schema file, +// learn more about it in the docs: https://pris.ly/d/prisma-schema + +generator client { + provider = "prisma-client-js" +} + +generator nexusPrisma { + provider = "nexus-prisma" +} + +datasource db { + provider = "postgresql" + url = env("BACKEND_DATABASE_URL") +} + +enum Role { + SUPER_ADMIN + ADMIN + TEACHER + STUDENT +} + +model User { + id String @id @default(uuid()) + firstname String + lastname String + email String @unique + password String + blocked Boolean @default(false) + role Role + teacher Teacher? + student Student? +} + +model Teacher { + id String @id @default(uuid()) + user User @relation(fields: [userId], references: [id]) + userId String @unique + maxStudents Int +} + +model Student { + id String @id @default(uuid()) + user User @relation(fields: [userId], references: [id]) + userId String @unique +} diff --git a/docker/backend_old/src/context.ts b/docker/backend_old/src/context.ts new file mode 100644 index 0000000..a89e936 --- /dev/null +++ b/docker/backend_old/src/context.ts @@ -0,0 +1,7 @@ +import { PrismaClient } from "@prisma/client"; + +const client = new PrismaClient(); + +export class Context { + constructor(public readonly req: unknown, public readonly prisma = client) {} +} diff --git a/docker/backend_old/src/index.ts b/docker/backend_old/src/index.ts new file mode 100644 index 0000000..53fa572 --- /dev/null +++ b/docker/backend_old/src/index.ts @@ -0,0 +1,34 @@ +import { createServer, useMaskedErrors } from "graphql-yoga"; +import { useGraphQlJit } from "@envelop/graphql-jit"; +import { useResourceLimitations } from "@envelop/resource-limitations"; +import { useApolloServerErrors } from "@envelop/apollo-server-errors"; + +import { schema } from "./schema"; +import { Context } from "./context"; + +const isProduction = process.env.NODE_ENV !== "development"; + +console.log(`NODE_ENV: ${process.env.NODE_ENV}`); +console.log("Starting server..."); + +const server = createServer({ + endpoint: "/", + port: 8080, + graphiql: false, + schema: schema as any, + async context(req) { + return new Context(req); + }, + plugins: [ + useGraphQlJit(), + useResourceLimitations({ + extensions: true, + }), + useMaskedErrors(), + useApolloServerErrors({ + debug: !isProduction, + }), + ], +}); + +server.start(() => console.log("Server is running on http://localhost:8080")); diff --git a/docker/backend_old/src/schema/index.ts b/docker/backend_old/src/schema/index.ts new file mode 100644 index 0000000..b0b357b --- /dev/null +++ b/docker/backend_old/src/schema/index.ts @@ -0,0 +1,10 @@ +import { makeSchema } from "nexus"; + +import { Query } from "./query"; +import { Mutation } from "./mutation"; +import { User, UserCreateInput } from "./user"; +import { Role } from "./role"; + +export const schema = makeSchema({ + types: [Query, Mutation, User, UserCreateInput, Role], +}); diff --git a/docker/backend_old/src/schema/mutation.ts b/docker/backend_old/src/schema/mutation.ts new file mode 100644 index 0000000..a8288bb --- /dev/null +++ b/docker/backend_old/src/schema/mutation.ts @@ -0,0 +1,27 @@ +import { mutationType, arg, nonNull } from "nexus"; +import * as argon2 from "argon2"; + +import { Context } from "../context"; +import { User, UserCreateInput } from "./user"; + +export const Mutation = mutationType({ + definition(t) { + t.nonNull.field("createUser", { + type: User, + args: { + input: nonNull(arg({ type: UserCreateInput })), + }, + async resolve(_root, args, ctx: Context) { + return ctx.prisma.user.create({ + data: { + firstname: args.input.firstname, + lastname: args.input.lastname, + email: args.input.email, + password: await argon2.hash(args.input.password), + role: args.input.role, + }, + }); + }, + }); + }, +}); diff --git a/docker/backend_old/src/schema/query.ts b/docker/backend_old/src/schema/query.ts new file mode 100644 index 0000000..e617c0f --- /dev/null +++ b/docker/backend_old/src/schema/query.ts @@ -0,0 +1,33 @@ +import { queryType, idArg, nonNull } from "nexus"; + +import { Context } from "../context"; +import { User } from "./user"; + +export const Query = queryType({ + definition(t) { + t.nonNull.boolean("ok", { + resolve() { + return true; + }, + }); + t.field("user", { + type: User, + args: { + id: nonNull(idArg()), + }, + resolve(_root, args, ctx: Context) { + return ctx.prisma.user.findUnique({ + where: { + id: args.id, + }, + }); + }, + }); + t.nonNull.list.nonNull.field("users", { + type: User, + resolve(_root, _args, ctx: Context) { + return ctx.prisma.user.findMany(); + }, + }); + }, +}); diff --git a/docker/backend_old/src/schema/role.ts b/docker/backend_old/src/schema/role.ts new file mode 100644 index 0000000..5d7bc6c --- /dev/null +++ b/docker/backend_old/src/schema/role.ts @@ -0,0 +1,7 @@ +import { enumType } from "nexus"; +import * as nPrisma from "nexus-prisma"; + +export const Role = enumType({ + name: nPrisma.Role.name, + members: nPrisma.Role.members, +}); diff --git a/docker/backend_old/src/schema/user.ts b/docker/backend_old/src/schema/user.ts new file mode 100644 index 0000000..c5fc43b --- /dev/null +++ b/docker/backend_old/src/schema/user.ts @@ -0,0 +1,28 @@ +import { objectType, inputObjectType } from "nexus"; +import * as nPrisma from "nexus-prisma"; + +import { Role } from "./role"; + +export const User = objectType({ + name: nPrisma.User.$name, + definition(t) { + t.field(nPrisma.User.id); + t.field(nPrisma.User.firstname); + t.field(nPrisma.User.lastname); + t.field(nPrisma.User.email); + t.field(nPrisma.User.role); + t.field(nPrisma.User.blocked); + }, +}); + +export const UserCreateInput = inputObjectType({ + name: "UserCreateInput", + definition(t) { + t.nonNull.string("firstname"); + t.nonNull.string("lastname"); + t.nonNull.string("email"); + t.nonNull.string("password"); + t.nonNull.field("role", { type: Role }); + t.boolean("blocked", { default: false }); + }, +}); diff --git a/docker/backend_old/tsconfig.json b/docker/backend_old/tsconfig.json new file mode 100644 index 0000000..1efc77b --- /dev/null +++ b/docker/backend_old/tsconfig.json @@ -0,0 +1,103 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Projects */ + // "incremental": true, /* Enable incremental compilation */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es6" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, + "lib": [ + "ESNext" + ] /* Specify a set of bundled library declaration files that describe the target runtime environment. */, + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ + // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + + /* Modules */ + "module": "commonjs" /* Specify what module code is generated. */, + "rootDir": "./src" /* Specify the root folder within your source files. */, + // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "resolveJsonModule": true, /* Enable importing .json files */ + // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ + + /* Emit */ + "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */, + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "sourceMap": true /* Create source map files for emitted JavaScript files. */, + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ + "outDir": "./dist" /* Specify an output folder for all emitted files. */, + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */, + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, + + /* Type Checking */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ + // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ + // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/docker/backend_old/yarn.lock b/docker/backend_old/yarn.lock new file mode 100644 index 0000000..b43c92c --- /dev/null +++ b/docker/backend_old/yarn.lock @@ -0,0 +1,1380 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ardatan/graphql-helix@0.1.12": + version "0.1.12" + resolved "https://registry.yarnpkg.com/@ardatan/graphql-helix/-/graphql-helix-0.1.12.tgz#63a4ccb3b566875268ebb24fd62611c2ca99435d" + integrity sha512-0fWr5A0/i69p6oORcwvInfPoKLO/JbcxtsukABGBp0UbnOjrDipHGNgEe8gReX2ROEyW45fj+LukgxzMldsUDg== + dependencies: + cross-undici-fetch "^0.1.10" + +"@envelop/apollo-server-errors@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@envelop/apollo-server-errors/-/apollo-server-errors-1.2.1.tgz#b1c65640db2a7ffd72bef7b3c34f8fb5c61f00b2" + integrity sha512-NPdccsswP0UrHORH+xpaPNLqnuUfqt3A3A+BrhOpy/SDRVspS7Xi0qZ+wj3EZOnG+FVnS0xEDPtAw8eEemJHuw== + dependencies: + apollo-server-errors "3.3.0" + +"@envelop/core@^1.6.1", "@envelop/core@^1.6.2": + version "1.6.5" + resolved "https://registry.yarnpkg.com/@envelop/core/-/core-1.6.5.tgz#dd8728b6d5732aab37105a98388804a22f53f033" + integrity sha512-HcpQDFo5CLyzWJPbtX34jz2rViMcq8tlRgv5KAnpGDEMZnY+lO/Fx9C0eC0K0H4pRAX09kNvMg5JC/9ruRKGRg== + dependencies: + "@envelop/types" "1.5.1" + +"@envelop/disable-introspection@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@envelop/disable-introspection/-/disable-introspection-1.2.1.tgz#fc8dd30a1a87f9df2f176fa628aa34718e1535f5" + integrity sha512-NhnMFTbvbkqf9StBp3sxqaqADP1MteQZIgtrzoosxrc+fWKqQf1G3XSbTG1F7HVr5uLNvF+are5CQL1Je0ukrw== + +"@envelop/extended-validation@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@envelop/extended-validation/-/extended-validation-1.3.1.tgz#6c5fb0a3d2c174d8f3971467d89804d719b62c00" + integrity sha512-Jmn+RXB+sQ1DzHg69vPIYUN8R1i1CIysRUbDOYvuxkIF2dHV9rP+33E3syPpNSwYiRA5ZSiGYNLx6OhS1Ii0zg== + dependencies: + "@envelop/core" "^1.6.1" + "@graphql-tools/utils" "^8.5.3" + +"@envelop/graphql-jit@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@envelop/graphql-jit/-/graphql-jit-1.3.1.tgz#8ded44de52ca67da54297badbd949823f7c245b1" + integrity sha512-9BdMuQVt0/g1YkSQRzipCzgxp9UAC5DQw2yQXuCrXcdWPEaLxf6Nxokx0GznoxGxulGLiR/iTuboqH6Kt24HLA== + dependencies: + graphql-jit "^0.7.0" + tiny-lru "7.0.6" + +"@envelop/parser-cache@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@envelop/parser-cache/-/parser-cache-2.2.1.tgz#c4105c85ac46bee1951b7d91d47bf42f318ea973" + integrity sha512-7PHYjln5Jl0JieCd5mVCKZoCpxyL3EQf2etxvmB1ALB6D9QjLYSv+zSPQRT/rmeDtLDohFKVN6cIyhYNSUG2bQ== + dependencies: + tiny-lru "7.0.6" + +"@envelop/resource-limitations@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@envelop/resource-limitations/-/resource-limitations-0.4.1.tgz#bb47fe58da08e7cbf013d820b4175298db6aa477" + integrity sha512-lJ09FPs5x+tPjS7F/1288tCHb2HDfIfwqLNkroVBt7ggmQyxdFwi+oe/L3kUvJ2s/RqlEU7YoA0mVv5nr4mVoA== + dependencies: + "@envelop/extended-validation" "^1.3.1" + "@graphql-tools/utils" "^8.5.3" + +"@envelop/types@1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@envelop/types/-/types-1.5.1.tgz#8a47ca9f6e78b40b176dac0dea6c5045f92c644d" + integrity sha512-NrwLVzyNqiSzgRRqOxkU2IgRc5hSGS73VsgxqchU3jl36rYo7AXVAnITkytmB9wk+jN2vUOVvayLkaTXooARwg== + +"@envelop/validation-cache@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@envelop/validation-cache/-/validation-cache-2.3.0.tgz#71b3455757426a2f30c1179466fad546435ad6be" + integrity sha512-yCsACrSo3psIjxakfn5tJBG2jG7XAjCCyZJ1YCY3/jogzHAXL2ypRh4r5x0K/aivygf4TrgQQkyizYwM8v5ETw== + dependencies: + tiny-lru "7.0.6" + +"@graphql-tools/merge@^8.2.1": + version "8.2.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.1.tgz#bf83aa06a0cfc6a839e52a58057a84498d0d51ff" + integrity sha512-Q240kcUszhXiAYudjuJgNuLgy9CryDP3wp83NOZQezfA6h3ByYKU7xI6DiKrdjyVaGpYN3ppUmdj0uf5GaXzMA== + dependencies: + "@graphql-tools/utils" "^8.5.1" + tslib "~2.3.0" + +"@graphql-tools/schema@8.3.1": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.3.1.tgz#1ee9da494d2da457643b3c93502b94c3c4b68c74" + integrity sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ== + dependencies: + "@graphql-tools/merge" "^8.2.1" + "@graphql-tools/utils" "^8.5.1" + tslib "~2.3.0" + value-or-promise "1.0.11" + +"@graphql-tools/utils@^8.5.1", "@graphql-tools/utils@^8.5.3": + version "8.5.5" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.5.5.tgz#019ddb99719feb19602afdb537c06e463df674a9" + integrity sha512-y7zRXWIUI73X+9/rf/0KzrNFMlpRKFfzLiwdbIeWwgLs+NV9vfUOoVkX8luXX6LwQxhSypHATMiwZGM2ro/wJA== + dependencies: + tslib "~2.3.0" + +"@graphql-typed-document-node/core@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.0.tgz#0eee6373e11418bfe0b5638f654df7a4ca6a3950" + integrity sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg== + +"@graphql-typed-document-node/core@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052" + integrity sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg== + +"@graphql-yoga/core@0.2.0-alpha.5": + version "0.2.0-alpha.5" + resolved "https://registry.yarnpkg.com/@graphql-yoga/core/-/core-0.2.0-alpha.5.tgz#a30cdb3bbd737497b7e5f70bc51a07d740daa51a" + integrity sha512-BrFpe3nKrJ5S0b9Vvjfg4IpuoICUDiMCvilC7Yj/RIfW8QYXZyxImWJdztxgSfGEE9e0WdHP/9HKE3WnYOGktQ== + dependencies: + "@envelop/core" "^1.6.2" + "@envelop/disable-introspection" "^1.2.1" + "@envelop/parser-cache" "^2.2.1" + "@envelop/validation-cache" "2.3.0" + "@graphql-tools/schema" "8.3.1" + "@graphql-yoga/handler" "0.2.0-alpha.2" + +"@graphql-yoga/handler@0.2.0-alpha.2": + version "0.2.0-alpha.2" + resolved "https://registry.yarnpkg.com/@graphql-yoga/handler/-/handler-0.2.0-alpha.2.tgz#2f3275418e60f4483aa8f35e90ba1970698443a4" + integrity sha512-gwFRYWVGUaI0ufIejnGbUzmGaVjYXAv8V56pmdk58YriclsRHi/SozJPJc56lMZUj3Szf3C/gUBsyMZrupx/nQ== + dependencies: + "@ardatan/graphql-helix" "0.1.12" + cross-undici-fetch "0.1.12" + +"@graphql-yoga/subscription@0.1.0-alpha.0": + version "0.1.0-alpha.0" + resolved "https://registry.yarnpkg.com/@graphql-yoga/subscription/-/subscription-0.1.0-alpha.0.tgz#9bb5b09313d048d9ebc53c87db92585065d1e6db" + integrity sha512-u36NcVTrk8XJC9FkzqUdZVN2G0fqsV2WxtTv7JDteVxJfHxCBQuVdKVUuUO9EplYIo6ph1Sba/o5r9gmIstyUA== + dependencies: + "@repeaterjs/repeater" "^3.0.4" + +"@jsdevtools/ono@7.1.3", "@jsdevtools/ono@^7.1.3": + version "7.1.3" + resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" + integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== + +"@mapbox/node-pre-gyp@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.8.tgz#32abc8a5c624bc4e46c43d84dfb8b26d33a96f58" + integrity sha512-CMGKi28CF+qlbXh26hDe6NxCd7amqeAzEqnS6IHeO6LoaKyM/n+Xw3HT1COdq8cuioOdlKdqn/hCmqPUOMOywg== + dependencies: + detect-libc "^1.0.3" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.5" + nopt "^5.0.0" + npmlog "^5.0.1" + rimraf "^3.0.2" + semver "^7.3.5" + tar "^6.1.11" + +"@phc/format@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@phc/format/-/format-1.0.0.tgz#b5627003b3216dc4362125b13f48a4daa76680e4" + integrity sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ== + +"@prisma/client@^3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-3.7.0.tgz#9cafc105f12635c95e9b7e7b18e8fbf52cf3f18a" + integrity sha512-fUJMvBOX5C7JPc0e3CJD6Gbelbu4dMJB4ScYpiht8HMUnRShw20ULOipTopjNtl6ekHQJ4muI7pXlQxWS9nMbw== + dependencies: + "@prisma/engines-version" "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f" + +"@prisma/debug@3.7.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-3.7.0.tgz#eb4560cd14f4cf15186f057d712b7eb2042c309a" + integrity sha512-3FdQRGUt2zSe1D+RnCh2wmbCiMmhX+BKNRnC6Ic8KHayXMbEuRR4Ofgt0AZHRCdEQBwVFvM2Yep9zN3hNnWssw== + dependencies: + "@types/debug" "4.1.7" + ms "2.1.3" + +"@prisma/engines-version@3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f": + version "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f.tgz#055f36ac8b06c301332c14963cd0d6c795942c90" + integrity sha512-+qx2b+HK7BKF4VCa0LZ/t1QCXsu6SmvhUQyJkOD2aPpmOzket4fEnSKQZSB0i5tl7rwCDsvAiSeK8o7rf+yvwg== + +"@prisma/engines@3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f": + version "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f.tgz#12f28d5b78519fbd84c89a5bdff457ff5095e7a2" + integrity sha512-W549ub5NlgexNhR8EFstA/UwAWq3Zq0w9aNkraqsozVCt2CsX+lK4TK7IW5OZVSnxHwRjrgEAt3r9yPy8nZQRg== + +"@prisma/generator-helper@^3.6.0": + version "3.7.0" + resolved "https://registry.yarnpkg.com/@prisma/generator-helper/-/generator-helper-3.7.0.tgz#c688309bc0f665e140889aaca6b7d7e103e18515" + integrity sha512-jH5Sd9vXO+ER7yZrx7ah1gcUGcBW7ljk31t+TMMET6J8Wd7LOKgVWJ6O5IkPfw7KGuuFp8SolcivvGTsH4gsSA== + dependencies: + "@prisma/debug" "3.7.0" + "@types/cross-spawn" "6.0.2" + chalk "4.1.2" + cross-spawn "7.0.3" + +"@repeaterjs/repeater@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca" + integrity sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA== + +"@types/cross-spawn@6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.2.tgz#168309de311cd30a2b8ae720de6475c2fbf33ac7" + integrity sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw== + dependencies: + "@types/node" "*" + +"@types/debug@4.1.7": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" + integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + dependencies: + "@types/ms" "*" + +"@types/ms@*": + version "0.7.31" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" + integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== + +"@types/node@*", "@types/node@^17.0.5": + version "17.0.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.5.tgz#57ca67ec4e57ad9e4ef5a6bab48a15387a1c83e0" + integrity sha512-w3mrvNXLeDYV1GKTZorGJQivK6XLCoGwpnyJFbJVK/aTBQUxOCaa/GlFAAN3OTDFcb7h5tiFG+YXCO2By+riZw== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^6.11.0: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.1.0: + version "8.8.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb" + integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +apollo-server-errors@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-3.3.0.tgz#ac8ceb1400064312f983d8d70195693fbcf2be3c" + integrity sha512-9/MNlPZBbEjcCdJcUSbKbVEBT9xZS8GSpX7T/TyzcxHSbsXJszSDSipQNGC+PRKTKAUnv61IONScVyLKEZ5XEQ== + +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz#372e0e7bd279d8e94c653aaa1f67200884bf3e1c" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + +argon2@^0.28.3: + version "0.28.3" + resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.28.3.tgz#e5234eccf20a643ffc3b1bbd1aa9e81092e0d8e9" + integrity sha512-NkEJOImg+T7nnkx6/Fy8EbjZsF20hbBBKdVP/YUxujuLTAjIODmrFeY4vVpekKwGAGDm6roXxluFQ+CIaoVrbg== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.7" + "@phc/format" "^1.0.0" + node-addon-api "^4.2.0" + opencollective-postinstall "^2.0.3" + +args@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/args/-/args-5.0.1.tgz#4bf298df90a4799a09521362c579278cc2fdd761" + integrity sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ== + dependencies: + camelcase "5.0.0" + chalk "2.4.2" + leven "2.1.0" + mri "1.1.4" + +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +camelcase@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" + integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== + +chalk@2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@4.1.2, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +colorette@^2.0.7: + version "2.0.16" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" + integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +console-control-strings@^1.0.0, console-control-strings@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +cookie@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + +core-js@^3.4.1: + version "3.20.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.1.tgz#eb1598047b7813572f1dc24b7c6a95528c99eef3" + integrity sha512-btdpStYFQScnNVQ5slVcr858KP0YWYjV16eGJQw8Gg7CWtu/2qNvIM3qVRIR3n1pK2R9NNOrTevbvAYxajwEjg== + +cross-spawn@7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cross-undici-fetch@0.1.12, cross-undici-fetch@^0.1.10: + version "0.1.12" + resolved "https://registry.yarnpkg.com/cross-undici-fetch/-/cross-undici-fetch-0.1.12.tgz#2985bdbb28c182eae1744832c087559083ac06db" + integrity sha512-JNUr0ANEwc3MEUT5xBl2fVnCJqcPa7hpQfEYNsrCG/7/M4pUH5W0nQOe6FKAQGB6SqFPyAeoEn8G375QXWxwWQ== + dependencies: + abort-controller "^3.0.0" + form-data-encoder "^1.7.1" + formdata-node "^4.3.1" + node-fetch "^2.6.5" + undici "^4.9.3" + +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + +debug@4, debug@^4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +decimal.js@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +dindist@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/dindist/-/dindist-1.0.2.tgz#cd7eb84fba1b6c4d9c6c2cc675db15168a173c82" + integrity sha512-RLoPvdwNGOO4OAABtng/uP81K1MVfbBJpe9f+/e6w530SqSJcFfRzuDRf1kJX+mhxwo6TFOuj5khaDQGZJZUYg== + dependencies: + fast-json-parse "^1.0.3" + objectorarray "^1.0.4" + +duplexify@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0" + integrity sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.0" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-parse@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" + integrity sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-json-stringify@^1.13.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-1.21.0.tgz#51bc8c6d77d8c7b2cc7e5fa754f7f909f9e1262f" + integrity sha512-xY6gyjmHN3AK1Y15BCbMpeO9+dea5ePVsp3BouHCdukcx0hOHbXwFhRodhcI0NpZIgDChSeAKkHW9YjKvhwKBA== + dependencies: + ajv "^6.11.0" + deepmerge "^4.2.2" + string-similarity "^4.0.1" + +fast-redact@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.0.2.tgz#c940ba7162dde3aeeefc522926ae8c5231412904" + integrity sha512-YN+CYfCVRVMUZOUPeinHNKgytM1wPI/C/UCLEi56EsY2dwwvI00kIJHJoI7pMVqGoMew8SMZ2SSfHKHULHXDsg== + +fast-safe-stringify@^2.0.7: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + +fastify-warning@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/fastify-warning/-/fastify-warning-0.2.0.tgz#e717776026a4493dc9a2befa44db6d17f618008f" + integrity sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw== + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +floggy@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/floggy/-/floggy-0.3.1.tgz#bc009cc54623c655a7911a38d7c2155b0fe18d79" + integrity sha512-qNvfLv+wAvzLEG3KemsbrXZDxOq0hx83+NuzVXkFMpIP/Qh2DHK5Qr2kdQL/j7P8+GkHP0JQcGnvnPZLQE2B1w== + dependencies: + chalk "^4.1.2" + fp-ts "^2.11.3" + lodash "^4.17.21" + strip-ansi "6" + +form-data-encoder@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96" + integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== + +formdata-node@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.3.1.tgz#e7b78a2a51f524ccc483b4d223c89690fd22061d" + integrity sha512-8xKSa9et4zb+yziWsD/bI+EYjdg1z2p9EpKr+o+Yk12F/wP66bmDdvjj2ZXd2K/MJlR3HBzWnuV7f82jzHRqCA== + dependencies: + node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.1" + +fp-ts@^2.11.3: + version "2.11.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.11.5.tgz#97cceb26655b1452d7088d6fb0864f84cceffbe4" + integrity sha512-OqlwJq1BdpB83BZXTqI+dNcA6uYk6qk4u9Cgnt64Y+XS7dwdbp/mobx8S2KXf2AXH+scNmA/UVK3SEFHR3vHZA== + +fs-jetpack@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/fs-jetpack/-/fs-jetpack-4.3.0.tgz#8202abd21c9160faadf3c258b4cf918a74f680de" + integrity sha512-Zx4OJ8HyKvZL9sgxegMGRCgAJSQET5Cqpj/SESwnzqHruHvhkilJBGLoZf6EiYr3UWJDqcPoWDX7aAfaj7D9Qw== + dependencies: + minimatch "^3.0.2" + rimraf "^2.6.3" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" + console-control-strings "^1.0.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" + signal-exit "^3.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" + +generate-function@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" + integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== + dependencies: + is-property "^1.0.2" + +glob@^7.1.3: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graphql-jit@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/graphql-jit/-/graphql-jit-0.7.2.tgz#8cf08863c22377ea4a0c4b3c12a258f3c94934ca" + integrity sha512-u+FuMCBZfoB0v8Iw6blh+D3Feke2m6hS1TFhStJcLTCOyH+KmJPo3XCFJC5QLHxqT+PJEfyf0S+zKJUZjZrhsg== + dependencies: + "@graphql-typed-document-node/core" "3.1.0" + fast-json-stringify "^1.13.0" + generate-function "^2.3.1" + json-schema "^0.4.0" + lodash.memoize "^4.1.2" + lodash.merge "4.6.2" + lodash.mergewith "4.6.2" + +graphql-scalars@^1.13.6, graphql-scalars@^1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/graphql-scalars/-/graphql-scalars-1.14.1.tgz#546a12ac2901e17202f354c71e336942feb9afa2" + integrity sha512-IrJ2SI9IkCmWHyr7yIvtPNGWTWF3eTS+iNnw1DQMmEtsOgs1dUmT0ge+8M1+1xm+q3/5ZqB95yUYyThDyOTE+Q== + dependencies: + tslib "~2.3.0" + +graphql-yoga@^2.0.0-alpha.6: + version "2.0.0-alpha.6" + resolved "https://registry.yarnpkg.com/graphql-yoga/-/graphql-yoga-2.0.0-alpha.6.tgz#2f2d1f1025452ab4511e8c467b92a4b20533a0e5" + integrity sha512-cqiYnZU/apr0l7ocJjfTutvHw2OXI6IYIEbNMrlp68LU6FPvTZYvE94YIXD59rCb1Nh0D+/8G+HxRhIrM6GGMw== + dependencies: + "@ardatan/graphql-helix" "0.1.12" + "@envelop/core" "^1.6.2" + "@graphql-typed-document-node/core" "^3.1.1" + "@graphql-yoga/core" "0.2.0-alpha.5" + "@graphql-yoga/handler" "0.2.0-alpha.2" + "@graphql-yoga/subscription" "0.1.0-alpha.0" + light-my-request "^4.7.0" + pino "^7.2.0" + pino-pretty "^7.2.0" + +graphql@15: + version "15.8.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.8.0.tgz#33410e96b012fa3bdb1091cc99a94769db212b38" + integrity sha512-5gghUc24tP9HRznNpV2+FIoq3xKkj5dTQqf4v0CpdPbFVwFkWoxOM+o+2OC9ZSvjEMTjfmG9QT+gcvggTwW1zw== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-property@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +iterall@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" + integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-schema@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +kleur@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d" + integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA== + +leven@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" + integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= + +light-my-request@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-4.7.0.tgz#5bacd17fa0eaf96fe5eed1682c5e0d361953cf46" + integrity sha512-LTa8YZp3K2AUpqUnwwKajoIHcsKOBnzwJNQSrk7unziPwo6CjOYjyO0F9wfkxFvP+nBsCGe3eMPnedVgIIgdAw== + dependencies: + ajv "^8.1.0" + cookie "^0.4.0" + fastify-warning "^0.2.0" + set-cookie-parser "^2.4.1" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + +lodash.merge@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.mergewith@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" + integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== + +lodash@^4.17.20, lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minipass@^3.0.0: + version "3.1.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" + integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + dependencies: + yallist "^4.0.0" + +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + +mkdirp@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mri@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a" + integrity sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nexus-prisma@^0.35.0: + version "0.35.0" + resolved "https://registry.yarnpkg.com/nexus-prisma/-/nexus-prisma-0.35.0.tgz#0d9c87b437a29804990b5597da6b33fa857d1ac9" + integrity sha512-loDL1emSv469s6ENJ8GIkbWAG1QavNShFfnZFrlxkEnAJZP023JwJOdJ/QcMCnu0LV2pTNB1YWl0F/wB1JvamQ== + dependencies: + "@prisma/generator-helper" "^3.6.0" + debug "^4.3.3" + decimal.js "^10.3.1" + dindist "^1.0.2" + expand-tilde "^2.0.2" + fs-jetpack "^4.3.0" + graphql-scalars "^1.13.6" + kleur "^4.1.4" + lodash "^4.17.21" + ono "^7.1.3" + pkg-up "^3.1.0" + pluralize "^8.0.0" + semver "^7.3.5" + setset "^0.0.8" + ts-replace-all "^1.0.0" + tslib "^2.3.1" + +nexus@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/nexus/-/nexus-1.1.0.tgz#3d8fa05c29e7a61aa55f64ef5e0ba43dd76b3ed6" + integrity sha512-jUhbg22gKVY2YwZm726BrbfHaQ7Xzc0hNXklygDhuqaVxCuHCgFMhWa2svNWd1npe8kfeiu5nbwnz+UnhNXzCQ== + dependencies: + iterall "^1.3.0" + tslib "^2.0.3" + +node-addon-api@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.2.0.tgz#117cbb5a959dff0992e1c586ae0393573e4d2a87" + integrity sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q== + +node-domexception@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^2.6.5: + version "2.6.6" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" + integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== + dependencies: + whatwg-url "^5.0.0" + +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== + dependencies: + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +objectorarray@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" + integrity sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg== + +on-exit-leak-free@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" + integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +ono@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/ono/-/ono-7.1.3.tgz#a054e96a388f566a6c4c95e1e92b9b253722d286" + integrity sha512-9jnfVriq7uJM4o5ganUY54ntUm+5EK21EGaQ5NWnkWg3zz5ywbbonlBguRcnmF1/HDiIe3zxNxXcO1YPBmPcQQ== + dependencies: + "@jsdevtools/ono" "7.1.3" + +opencollective-postinstall@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259" + integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q== + +p-limit@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +pino-abstract-transport@^0.5.0, pino-abstract-transport@v0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-0.5.0.tgz#4b54348d8f73713bfd14e3dc44228739aa13d9c0" + integrity sha512-+KAgmVeqXYbTtU2FScx1XS3kNyfZ5TrXY07V96QnUSFqo2gAqlvmaxH67Lj7SWazqsMabf+58ctdTcBgnOLUOQ== + dependencies: + duplexify "^4.1.2" + split2 "^4.0.0" + +pino-pretty@^7.2.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-7.3.0.tgz#277fdc2306a2f6d727a1127e7747d1c078efdd4b" + integrity sha512-HAhShJ2z2QzxXhYAn6XfwYpF13o1PQbjzSNA9q+30FAvhjOmeACit9lprhV/mCOw/8YFWSyyNk0YCq2EDYGYpw== + dependencies: + args "^5.0.1" + colorette "^2.0.7" + dateformat "^4.6.3" + fast-safe-stringify "^2.0.7" + joycon "^3.1.1" + pino-abstract-transport "^0.5.0" + pump "^3.0.0" + readable-stream "^3.6.0" + rfdc "^1.3.0" + secure-json-parse "^2.4.0" + sonic-boom "^2.2.0" + strip-json-comments "^3.1.1" + +pino-std-serializers@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-4.0.0.tgz#1791ccd2539c091ae49ce9993205e2cd5dbba1e2" + integrity sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q== + +pino@^7.2.0: + version "7.6.2" + resolved "https://registry.yarnpkg.com/pino/-/pino-7.6.2.tgz#73d09dcf13079fd0a2fa7e8648f715d5082e63d8" + integrity sha512-GTzW+HHOzUTaPIyvK6tasky2jMXF1o3iw7Oc2ik7qFjcaexXfyn6ej72XwX4O+wuRyFCbp3oKpv00htrPddv5A== + dependencies: + fast-redact "^3.0.0" + on-exit-leak-free "^0.2.0" + pino-abstract-transport v0.5.0 + pino-std-serializers "^4.0.0" + process-warning "^1.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.1.0" + safe-stable-stringify "^2.1.0" + sonic-boom "^2.2.1" + thread-stream "^0.13.0" + +pkg-up@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5" + integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA== + dependencies: + find-up "^3.0.0" + +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + +prisma@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-3.7.0.tgz#9c73eeb2f16f767fdf523d0f4cc4c749734d62e2" + integrity sha512-pzgc95msPLcCHqOli7Hnabu/GRfSGSUWl5s2P6N13T/rgMB+NNeKbxCmzQiZT2yLOeLEPivV6YrW1oeQIwJxcg== + dependencies: + "@prisma/engines" "3.7.0-31.8746e055198f517658c08a0c426c7eec87f5a85f" + +process-warning@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" + integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +readable-stream@^3.1.1, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +real-require@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381" + integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +rfdc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" + integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== + +rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-stable-stringify@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73" + integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg== + +secure-json-parse@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.4.0.tgz#5aaeaaef85c7a417f76271a4f5b0cc3315ddca85" + integrity sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg== + +semver@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.5: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-cookie-parser@^2.4.1: + version "2.4.8" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2" + integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== + +setset@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/setset/-/setset-0.0.8.tgz#4d68793e2d00ea10efdd09ca7647d14d3dcb51fa" + integrity sha512-NNyiUBzR6Q4Z0zHuSinXJehFEH/u2DoHSfHit5vQVqZHEwqlwzfxAOo5SfgkyFfgN85UJbax9jPXSULNyKIcBw== + dependencies: + "@jsdevtools/ono" "^7.1.3" + floggy "^0.3.1" + lodash "^4.17.20" + tslib "^2.2.0" + type-fest "^0.20.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.0: + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== + +sonic-boom@^2.2.0, sonic-boom@^2.2.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-2.4.2.tgz#34c0965b1a498abedaaca794c752d190f74b5e8f" + integrity sha512-zlOmAKFLJzTI+MbvmkWhnOOJ++NYo0Iy7F93ARNPmvZvpWG2l8Ff3uwM3CkpHqRw8v3pcRROScM5E+vbeTeOKw== + dependencies: + atomic-sleep "^1.0.0" + +split2@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" + integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + +string-similarity@^4.0.1: + version "4.0.4" + resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" + integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-ansi@6, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +tar@^6.1.11: + version "6.1.11" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + +thread-stream@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-0.13.0.tgz#c68054bdea250c5d8d400caa3233a150d5461cca" + integrity sha512-kTMZeX4Dzlb1zZ00/01aerGaTw2i8NE4sWF0TvF1uXewRhCiUjCvatQkvxIvFqauWG2ADFS2Wpd3qBeYL9i3dg== + dependencies: + real-require "^0.1.0" + +tiny-lru@7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-7.0.6.tgz#b0c3cdede1e5882aa2d1ae21cb2ceccf2a331f24" + integrity sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow== + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +ts-replace-all@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ts-replace-all/-/ts-replace-all-1.0.0.tgz#ef28283ccdb4da7d69fb03cf543e09e51711659b" + integrity sha512-6uBtdkw3jHXkPtx/e9xB/5vcngMm17CyJYsS2YZeQ+9FdRnt6Ev5g931Sg2p+dxbtMGoCm13m3ax/obicTZIkQ== + dependencies: + core-js "^3.4.1" + +tslib@^2.0.3, tslib@^2.2.0, tslib@^2.3.1, tslib@~2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + +type-fest@^0.20.0: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typescript@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.4.tgz#a17d3a0263bf5c8723b9c52f43c5084edf13c2e8" + integrity sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg== + +undici@^4.9.3: + version "4.12.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-4.12.1.tgz#3a7b5fb12f835a96a65397dd94578464b08d1c27" + integrity sha512-MSfap7YiQJqTPP12C11PFRs9raZuVicDbwsZHTjB0a8+SsCqt7KdUis54f373yf7ZFhJzAkGJLaKm0202OIxHg== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +value-or-promise@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.11.tgz#3e90299af31dd014fe843fe309cefa7c1d94b140" + integrity sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg== + +web-streams-polyfill@4.0.0-beta.1: + version "4.0.0-beta.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.1.tgz#3b19b9817374b7cee06d374ba7eeb3aeb80e8c95" + integrity sha512-3ux37gEX670UUphBF9AMCq8XM6iQ8Ac6A+DSRRjDoRBm1ufCkaCDdNVbaqq60PsEkdNlLKrGtv/YBP4EJXqNtQ== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== diff --git a/scripts/micrate.sh b/scripts/micrate.sh new file mode 100644 index 0000000..1d8dae5 --- /dev/null +++ b/scripts/micrate.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +docker-compose exec backend /micrate "$@"