diff --git a/.circleci/config.yml b/.circleci/config.yml index 28b1e1242..418a4b9fb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,9 +1,10 @@ version: 2.1 orbs: - helm: circleci/helm@1.1.2 + helm: circleci/helm@2.0.1 docker: circleci/docker@1.7.0 jq: circleci/jq@2.2.0 - node: circleci/node@5.0.2 + node: circleci/node@5.0.3 +# codecov: codecov/codecov@3.2.4 executors: backend_test: docker: @@ -132,10 +133,10 @@ jobs: command: | curl https://uploader.codecov.io/latest/linux/codecov -o /tmp/codecov chmod +x /tmp/codecov - /tmp/codecov -F backend - #- run: - # name: "Upload coverage" - # command: bash <(curl -s https://codecov.io/bash) + /tmp/codecov -F backend -n "${CIRCLE_BUILD_NUM}" + ### when codecov orb is enabled + # - codecov/upload: + # flags: backend # The resource_class feature allows configuring CPU and RAM resources for each job. Different resource classes are available for different executors. https://circleci.com/docs/2.0/configuration-reference/#resourceclass resource_class: large # could combine the artifacts in this step if needed, now the codecov/junit stuff combines automatically @@ -255,7 +256,6 @@ jobs: resource_class: large workflows: - version: 2 build-deploy: jobs: - code_style @@ -291,4 +291,4 @@ workflows: branches: only: - master - - staging + - staging \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 556490f34..8720eda1d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -70,7 +70,9 @@ const esLintConfig = { "plugin:@typescript-eslint/recommended", // "plugin:@typescript-eslint/recommended-requiring-type-checking", // these are a bit too strict for now "plugin:jsx-a11y/recommended", + "prettier", "plugin:@next/next/recommended", + "plugin:@next/next/core-web-vitals", ], settings: { react: { diff --git a/.prettierrc.js b/.prettierrc.js index afdc64e2a..a1c510355 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,3 +1,5 @@ +// @ts-check +/** @type {import("@ianvs/prettier-plugin-sort-imports").PrettierConfig} */ module.exports = { printWidth: 80, semi: false, @@ -15,7 +17,7 @@ module.exports = { "", "^/graphql", ], - plugins: [require.resolve("@ianvs/prettier-plugin-sort-imports")], + // plugins: [require.resolve("@ianvs/prettier-plugin-sort-imports")], importOrderBuiltinModulesToTop: true, importOrderSortSpecifiers: true, importOrderCaseInsensitive: true, diff --git a/backend/.prettierrc.js b/backend/.prettierrc.js new file mode 120000 index 000000000..01a7e980a --- /dev/null +++ b/backend/.prettierrc.js @@ -0,0 +1 @@ +../.prettierrc.js \ No newline at end of file diff --git a/backend/api/routes/__test__/__snapshots__/completions.test.ts.snap b/backend/api/routes/__test__/__snapshots__/completions.test.ts.snap index 891b0050a..a583251a7 100644 --- a/backend/api/routes/__test__/__snapshots__/completions.test.ts.snap +++ b/backend/api/routes/__test__/__snapshots__/completions.test.ts.snap @@ -1,28 +1,30 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`API /api/register-completions creates registered completions 1`] = ` -Array [ - Object { - "completion_id": "30000000-0000-0000-0000-000000000102", - "course_id": "00000000-0000-0000-0000-000000000002", - "created_at": Any, - "id": Any, - "organization_id": "10000000-0000-0000-0000-000000000102", - "real_student_number": "12345", - "registration_date": null, - "updated_at": Any, - "user_id": "20000000-0000-0000-0000-000000000102", - }, - Object { - "completion_id": "30000000-0000-0000-0000-000000000103", - "course_id": "00000000-0000-0000-0000-000000000001", - "created_at": Any, - "id": Any, - "organization_id": "10000000-0000-0000-0000-000000000102", - "real_student_number": "12345", - "registration_date": null, - "updated_at": Any, - "user_id": "20000000-0000-0000-0000-000000000102", - }, -] +{ + "addedCompletions": [ + { + "completion_id": "30000000-0000-0000-0000-000000000102", + "course_id": "00000000-0000-0000-0000-000000000002", + "created_at": Any, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "organization_id": "10000000-0000-0000-0000-000000000102", + "real_student_number": "12345", + "registration_date": null, + "updated_at": Any, + "user_id": "20000000-0000-0000-0000-000000000102", + }, + { + "completion_id": "30000000-0000-0000-0000-000000000103", + "course_id": "00000000-0000-0000-0000-000000000001", + "created_at": Any, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "organization_id": "10000000-0000-0000-0000-000000000102", + "real_student_number": "12345", + "registration_date": null, + "updated_at": Any, + "user_id": "20000000-0000-0000-0000-000000000102", + }, + ], +} `; diff --git a/backend/api/routes/__test__/__snapshots__/progress.test.ts.snap b/backend/api/routes/__test__/__snapshots__/progress.test.ts.snap index a2b902152..28a5d7304 100644 --- a/backend/api/routes/__test__/__snapshots__/progress.test.ts.snap +++ b/backend/api/routes/__test__/__snapshots__/progress.test.ts.snap @@ -1,9 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`API /api/progressv2 returns correct data on course id, include deleted false 1`] = ` -Object { - "data": Object { - "completion": Object { +{ + "data": { + "completion": { "certificate_id": null, "completion_date": "2000-01-01T08:00:00.000Z", "completion_language": null, @@ -21,8 +21,8 @@ Object { "user_upstream_id": 1, }, "course_id": "00000000-0000-0000-0000-000000000001", - "exercise_completions": Object { - "50000000-0000-0000-0000-000000000001": Object { + "exercise_completions": { + "50000000-0000-0000-0000-000000000001": { "completed": true, "exercise_id": "50000000-0000-0000-0000-000000000001", "max_points": 2, @@ -32,7 +32,7 @@ Object { "section": 1, "user_id": "20000000-0000-0000-0000-000000000102", }, - "50000000-0000-0000-0000-000000000002": Object { + "50000000-0000-0000-0000-000000000002": { "completed": false, "exercise_id": "50000000-0000-0000-0000-000000000002", "max_points": 3, @@ -49,9 +49,9 @@ Object { `; exports[`API /api/progressv2 returns correct data on course id, include deleted true 1`] = ` -Object { - "data": Object { - "completion": Object { +{ + "data": { + "completion": { "certificate_id": null, "completion_date": "2000-01-01T08:00:00.000Z", "completion_language": null, @@ -69,8 +69,8 @@ Object { "user_upstream_id": 1, }, "course_id": "00000000-0000-0000-0000-000000000001", - "exercise_completions": Object { - "50000000-0000-0000-0000-000000000001": Object { + "exercise_completions": { + "50000000-0000-0000-0000-000000000001": { "completed": true, "exercise_id": "50000000-0000-0000-0000-000000000001", "max_points": 2, @@ -80,7 +80,7 @@ Object { "section": 1, "user_id": "20000000-0000-0000-0000-000000000102", }, - "50000000-0000-0000-0000-000000000002": Object { + "50000000-0000-0000-0000-000000000002": { "completed": false, "exercise_id": "50000000-0000-0000-0000-000000000002", "max_points": 3, @@ -90,7 +90,7 @@ Object { "section": 2, "user_id": "20000000-0000-0000-0000-000000000102", }, - "50000000-0000-0000-0000-000000000005": Object { + "50000000-0000-0000-0000-000000000005": { "completed": false, "exercise_id": "50000000-0000-0000-0000-000000000005", "max_points": null, @@ -107,9 +107,9 @@ Object { `; exports[`API /api/progressv2 returns correct data on course slug, include deleted false 1`] = ` -Object { - "data": Object { - "completion": Object { +{ + "data": { + "completion": { "certificate_id": null, "completion_date": "2000-01-01T08:00:00.000Z", "completion_language": null, @@ -127,8 +127,8 @@ Object { "user_upstream_id": 1, }, "course_id": "00000000-0000-0000-0000-000000000001", - "exercise_completions": Object { - "50000000-0000-0000-0000-000000000001": Object { + "exercise_completions": { + "50000000-0000-0000-0000-000000000001": { "completed": true, "exercise_id": "50000000-0000-0000-0000-000000000001", "max_points": 2, @@ -138,7 +138,7 @@ Object { "section": 1, "user_id": "20000000-0000-0000-0000-000000000102", }, - "50000000-0000-0000-0000-000000000002": Object { + "50000000-0000-0000-0000-000000000002": { "completed": false, "exercise_id": "50000000-0000-0000-0000-000000000002", "max_points": 3, @@ -155,9 +155,9 @@ Object { `; exports[`API /api/progressv2 returns correct data on course slug, include deleted true 1`] = ` -Object { - "data": Object { - "completion": Object { +{ + "data": { + "completion": { "certificate_id": null, "completion_date": "2000-01-01T08:00:00.000Z", "completion_language": null, @@ -175,8 +175,8 @@ Object { "user_upstream_id": 1, }, "course_id": "00000000-0000-0000-0000-000000000001", - "exercise_completions": Object { - "50000000-0000-0000-0000-000000000001": Object { + "exercise_completions": { + "50000000-0000-0000-0000-000000000001": { "completed": true, "exercise_id": "50000000-0000-0000-0000-000000000001", "max_points": 2, @@ -186,7 +186,7 @@ Object { "section": 1, "user_id": "20000000-0000-0000-0000-000000000102", }, - "50000000-0000-0000-0000-000000000002": Object { + "50000000-0000-0000-0000-000000000002": { "completed": false, "exercise_id": "50000000-0000-0000-0000-000000000002", "max_points": 3, @@ -196,7 +196,7 @@ Object { "section": 2, "user_id": "20000000-0000-0000-0000-000000000102", }, - "50000000-0000-0000-0000-000000000005": Object { + "50000000-0000-0000-0000-000000000005": { "completed": false, "exercise_id": "50000000-0000-0000-0000-000000000005", "max_points": null, @@ -211,4 +211,3 @@ Object { }, } `; - diff --git a/backend/api/routes/__test__/__snapshots__/storedData.test.ts.snap b/backend/api/routes/__test__/__snapshots__/storedData.test.ts.snap index 879d0f292..0ee5ad7d0 100644 --- a/backend/api/routes/__test__/__snapshots__/storedData.test.ts.snap +++ b/backend/api/routes/__test__/__snapshots__/storedData.test.ts.snap @@ -1,10 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`API /api/temporary-stored-data get returns stored data from owned course 1`] = ` -Array [ - Object { - "completions": Array [ - Object { +[ + { + "completions": [ + { "certificate_id": null, "completion_date": "2000-01-01T08:00:00.000Z", "completion_language": null, @@ -22,14 +22,14 @@ Array [ "user_upstream_id": 1, }, ], - "storedData": Object { + "storedData": { "course_id": "00000000-0000-0000-0000-000000000001", "created_at": "1900-01-01T08:00:00.000Z", "data": "user1_foo", "updated_at": "1900-01-01T08:00:00.000Z", "user_id": "20000000-0000-0000-0000-000000000102", }, - "user": Object { + "user": { "administrator": false, "created_at": "1900-01-01T08:00:00.000Z", "email": "e@mail.com", diff --git a/backend/api/routes/__test__/completions.test.ts b/backend/api/routes/__test__/completions.test.ts index 434df9644..bb1e7f9d8 100644 --- a/backend/api/routes/__test__/completions.test.ts +++ b/backend/api/routes/__test__/completions.test.ts @@ -4,6 +4,7 @@ import { createRequestHelpers, fakeTMCCurrent, getTestContext, + ID_REGEX, RequestGet, RequestPost, } from "../../../tests" @@ -229,18 +230,22 @@ describe("API", () => { }, }) - expect(orderBy(addedCompletions, "completion_id")).toMatchSnapshot([ - { - id: expect.any(String), - created_at: expect.any(Date), - updated_at: expect.any(Date), - }, - { - id: expect.any(String), - created_at: expect.any(Date), - updated_at: expect.any(Date), - }, - ]) + expect({ + addedCompletions: orderBy(addedCompletions, "completion_id"), + }).toMatchSnapshot({ + addedCompletions: [ + { + id: expect.stringMatching(ID_REGEX), + created_at: expect.any(Date), + updated_at: expect.any(Date), + }, + { + id: expect.stringMatching(ID_REGEX), + created_at: expect.any(Date), + updated_at: expect.any(Date), + }, + ], + }) }) }) }) diff --git a/backend/bin/kafkaBridge.ts b/backend/bin/kafkaBridge.ts index 01568af0b..30eab2253 100644 --- a/backend/bin/kafkaBridge.ts +++ b/backend/bin/kafkaBridge.ts @@ -57,7 +57,9 @@ app.use(compression()) app.use(express.json()) app.use(morgan("combined")) +// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const port = parseInt(KAFKA_BRIDGE_SERVER_PORT || "3003") +// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const host = KAFKA_BRIDGE_SERVER_HOST || "0.0.0.0" app.post("/kafka-bridge/api/v0/event", async (req, res) => { diff --git a/backend/bin/kafkaConsumer/common/__test__/__snapshots__/userFunctions.test.ts.snap b/backend/bin/kafkaConsumer/common/__test__/__snapshots__/userFunctions.test.ts.snap index dc8ebbd55..6a99ebc03 100644 --- a/backend/bin/kafkaConsumer/common/__test__/__snapshots__/userFunctions.test.ts.snap +++ b/backend/bin/kafkaConsumer/common/__test__/__snapshots__/userFunctions.test.ts.snap @@ -1,15 +1,15 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`exercise completion utilities getExerciseCompletionsForCourses returns correctly only one course specified 1`] = ` -Array [ - Object { +[ + { "course_id": "00000000-0000-0000-0000-000000000667", "custom_id": "test_exercise_2", "exercise_id": "18180000-0000-0000-0000-000000000002", "max_points": 2, "n_points": "3.000000000000000000000000000000", }, - Object { + { "course_id": "00000000-0000-0000-0000-000000000667", "custom_id": "test_exercise_6", "exercise_id": "18180000-0000-0000-0000-000000000006", @@ -20,22 +20,22 @@ Array [ `; exports[`exercise completion utilities getExerciseCompletionsForCourses returns correctly with multiple courses specified 1`] = ` -Array [ - Object { +[ + { "course_id": "00000000-0000-0000-0000-000000000667", "custom_id": "test_exercise_2", "exercise_id": "18180000-0000-0000-0000-000000000002", "max_points": 2, "n_points": "3.000000000000000000000000000000", }, - Object { + { "course_id": "00000000-0000-0000-0000-000000000668", "custom_id": "test_exercise_5_other_course", "exercise_id": "18180000-0000-0000-0000-000000000005", "max_points": 1, "n_points": "1.000000000000000000000000000000", }, - Object { + { "course_id": "00000000-0000-0000-0000-000000000667", "custom_id": "test_exercise_6", "exercise_id": "18180000-0000-0000-0000-000000000006", @@ -46,8 +46,8 @@ Array [ `; exports[`exercise completion utilities getExerciseCompletionsForCourses returns correctly with other user 1`] = ` -Array [ - Object { +[ + { "course_id": "00000000-0000-0000-0000-000000000667", "custom_id": "test_exercise_4", "exercise_id": "18180000-0000-0000-0000-000000000004", diff --git a/backend/bin/kafkaConsumer/common/handleMessage.ts b/backend/bin/kafkaConsumer/common/handleMessage.ts index b73577e2f..da2f48f16 100644 --- a/backend/bin/kafkaConsumer/common/handleMessage.ts +++ b/backend/bin/kafkaConsumer/common/handleMessage.ts @@ -93,6 +93,7 @@ export const handleMessage = async ({ const commit = async (kafkaContext: KafkaContext, message: KafkaMessage) => { const { logger, consumer } = kafkaContext + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const commitCounter = commitCounterMap.get(message.partition) || 0 commitCounterMap.set(message.partition, commitCounter + 1) diff --git a/backend/bin/kafkaConsumer/common/userCourseProgress/BAI/progress.ts b/backend/bin/kafkaConsumer/common/userCourseProgress/BAI/progress.ts index de0a4515d..482a94b3b 100644 --- a/backend/bin/kafkaConsumer/common/userCourseProgress/BAI/progress.ts +++ b/backend/bin/kafkaConsumer/common/userCourseProgress/BAI/progress.ts @@ -181,6 +181,7 @@ export const getProgress = ({ highestTier, totalExerciseCompletions, }: GetProgressArgs) => { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const pointsProgress = (n_points || 0) / (max_points || 1) const newProgress = { progress: [ diff --git a/backend/bin/kafkaConsumer/util/index.ts b/backend/bin/kafkaConsumer/util/index.ts index 9ce49dd97..1fa3822e6 100644 --- a/backend/bin/kafkaConsumer/util/index.ts +++ b/backend/bin/kafkaConsumer/util/index.ts @@ -3,7 +3,7 @@ import { DateTime } from "luxon" type DateTimeKeys = keyof typeof DateTime type DateTimeFromStringFunctions = { [K in DateTimeKeys]: K extends `from${infer Type}` - ? typeof DateTime[K] extends (text: string) => DateTime + ? (typeof DateTime)[K] extends (text: string) => DateTime ? `from${Type}` : never : never diff --git a/backend/bin/syncTMCUsers.ts b/backend/bin/syncTMCUsers.ts index 7a0b9cf1b..583442840 100644 --- a/backend/bin/syncTMCUsers.ts +++ b/backend/bin/syncTMCUsers.ts @@ -1,5 +1,4 @@ // import { PrismaClient } from "@prisma/client" - import axios from "axios" import { groupBy, orderBy } from "lodash" import * as winston from "winston" @@ -12,7 +11,7 @@ import { notEmpty } from "../util/notEmpty" import { TMCError } from "./lib/errors" import sentryLogger from "./lib/logger" -const URL = `${TMC_HOST || ""}/api/v8/users/recently_changed_user_details` +const URL = `${TMC_HOST ?? ""}/api/v8/users/recently_changed_user_details` export interface Change { id: number diff --git a/backend/config.ts b/backend/config.ts index 070c9db4c..cb0a604fc 100644 --- a/backend/config.ts +++ b/backend/config.ts @@ -63,7 +63,7 @@ export const AVOIN_TOKEN = process.env.AVOIN_TOKEN // certificates api export const CERTIFICATES_URL = - process.env.CERTIFICATES_URL || "https://certificates.mooc.fi" + process.env.CERTIFICATES_URL ?? "https://certificates.mooc.fi" // userAppDatum related export const CONFIG_NAME = process.env.CONFIG_NAME diff --git a/backend/config/languageConfig.ts b/backend/config/languageConfig.ts index ac6454ffd..5731366b1 100644 --- a/backend/config/languageConfig.ts +++ b/backend/config/languageConfig.ts @@ -193,7 +193,7 @@ export const languageInfo = [ }, ] as const -export type LanguageInfo = typeof languageInfo[number] +export type LanguageInfo = (typeof languageInfo)[number] export type LanguageAbbreviation = LanguageInfo["language"] export type CompletionLanguage = LanguageInfo["completion_language"] diff --git a/backend/graphql/CertificateAvailability.ts b/backend/graphql/CertificateAvailability.ts index 018cb5795..e6c23977b 100644 --- a/backend/graphql/CertificateAvailability.ts +++ b/backend/graphql/CertificateAvailability.ts @@ -4,7 +4,7 @@ export const CertificateAvailability = objectType({ name: "CertificateAvailability", definition(t) { t.boolean("completed_course") - t.nullable.string("existing_certificate") - t.nullable.boolean("honors") + t.string("existing_certificate") + t.boolean("honors") }, }) diff --git a/backend/graphql/Completion/index.ts b/backend/graphql/Completion/index.ts index e052193cc..06ae979b9 100644 --- a/backend/graphql/Completion/index.ts +++ b/backend/graphql/Completion/index.ts @@ -1,4 +1,4 @@ -// generated Tue Sep 27 2022 11:23:58 GMT+0300 (Itä-Euroopan kesäaika) +// generated Fri Dec 02 2022 11:28:08 GMT+0200 (Itä-Euroopan normaaliaika) export * from "./input" export * from "./model" diff --git a/backend/graphql/Completion/input.ts b/backend/graphql/Completion/input.ts index d38f09cc4..2ab55e614 100644 --- a/backend/graphql/Completion/input.ts +++ b/backend/graphql/Completion/input.ts @@ -5,8 +5,8 @@ export const CompletionArg = inputObjectType({ definition(t) { t.nonNull.string("completion_id") t.nonNull.string("student_number") - t.nullable.boolean("eligible_for_ects") - t.nullable.int("tier") + t.boolean("eligible_for_ects") + t.int("tier") }, }) @@ -14,8 +14,8 @@ export const ManualCompletionArg = inputObjectType({ name: "ManualCompletionArg", definition(t) { t.nonNull.string("user_id") - t.nullable.string("grade") - t.nullable.field("completion_date", { type: "DateTime" }) - t.nullable.int("tier") + t.string("grade") + t.field("completion_date", { type: "DateTime" }) + t.int("tier") }, }) diff --git a/backend/graphql/Completion/model.ts b/backend/graphql/Completion/model.ts index 40e58444d..705599264 100644 --- a/backend/graphql/Completion/model.ts +++ b/backend/graphql/Completion/model.ts @@ -31,37 +31,7 @@ export const Completion = objectType({ t.model.tier() t.model.completion_registration_attempt_date() - // we're not querying completion course languages for now, and this was buggy - /* t.field("course", { - type: "Course", - args: { - language: schema.nullable(stringArg()), - }, - resolve: async (parent, args, ctx) => { - const { language } = args - const { prisma } = ctx - - const course = await prisma.course({ id: parent.course }) - - if (language) { - const course_translations = await prisma.courseTranslations({ - where: { course, language }, - }) - - if (!course_translations.length) { - return course - } - - const { name = course.name, description } = course_translations[0] - - return { ...course, name, description } - } - - return course - }, - }) - */ - t.nullable.field("user", { + t.field("user", { type: "User", resolve: async (parent, _, ctx) => { if (ctx.disableRelations) { @@ -77,7 +47,7 @@ export const Completion = objectType({ }, }) - t.nullable.field("completion_link", { + t.field("completion_link", { type: "String", resolve: async (parent, _, ctx) => { if (!parent.course_id) { @@ -149,7 +119,7 @@ export const Completion = objectType({ }, }) - t.nullable.field("certificate_availability", { + t.field("certificate_availability", { type: "CertificateAvailability", resolve: async ({ course_id, user_upstream_id }, _, ctx) => { if (!course_id) { @@ -207,11 +177,7 @@ export const Completion = objectType({ ) } - if (!certificate_availability) { - return null - } - - return certificate_availability + return certificate_availability ?? null }, }) }, diff --git a/backend/graphql/Completion/mutations.ts b/backend/graphql/Completion/mutations.ts index 5bcb0eb3b..7bc742351 100644 --- a/backend/graphql/Completion/mutations.ts +++ b/backend/graphql/Completion/mutations.ts @@ -1,14 +1,5 @@ import { chunk, difference, groupBy } from "lodash" -import { - arg, - extendType, - idArg, - intArg, - list, - nonNull, - nullable, - stringArg, -} from "nexus" +import { arg, extendType, idArg, intArg, list, nonNull, stringArg } from "nexus" import { v4 as uuidv4 } from "uuid" import { Completion } from "@prisma/client" @@ -30,7 +21,7 @@ export const CompletionMutations = extendType({ user: nonNull(idArg()), course: nonNull(idArg()), completion_language: stringArg(), - tier: nullable(intArg()), + tier: intArg(), }, authorize: isAdmin, resolve: (_, args, ctx) => { @@ -61,7 +52,7 @@ export const CompletionMutations = extendType({ t.list.nonNull.field("addManualCompletion", { type: "Completion", args: { - completions: list(arg({ type: "ManualCompletionArg" })), + completions: list(nonNull(arg({ type: "ManualCompletionArg" }))), course_id: nonNull(stringArg()), }, authorize: isAdmin, diff --git a/backend/graphql/Completion/queries.ts b/backend/graphql/Completion/queries.ts index 2db7ac154..6dea641f8 100644 --- a/backend/graphql/Completion/queries.ts +++ b/backend/graphql/Completion/queries.ts @@ -1,5 +1,4 @@ // import { convertPagination } from "../../util/db-functions" - import { ForbiddenError } from "apollo-server-express" import { merge } from "lodash" import { extendType, idArg, intArg, nonNull, stringArg } from "nexus" diff --git a/backend/graphql/Course/__test__/Course.mutations.test.ts b/backend/graphql/Course/__test__/Course.mutations.test.ts new file mode 100644 index 000000000..3046685b6 --- /dev/null +++ b/backend/graphql/Course/__test__/Course.mutations.test.ts @@ -0,0 +1,606 @@ +import { createReadStream } from "fs" + +import { gql } from "graphql-request" +import { mocked } from "jest-mock" +import { omit } from "lodash" + +import KafkaProducer from "../../../services/kafkaProducer" +import { fakeTMCCurrent, getTestContext, ID_REGEX } from "../../../tests" +import { adminUserDetails, normalUserDetails } from "../../../tests/data" +import { seed } from "../../../tests/data/seed" +import { courseInclude } from "./util" + +jest.mock("../../../services/kafkaProducer") + +const ctx = getTestContext() +const tmc = fakeTMCCurrent({ + "Bearer normal": [200, normalUserDetails], + "Bearer admin": [200, adminUserDetails], +}) + +const anyPhoto = { + photo_id: expect.stringMatching(ID_REGEX), + photo: { + original: expect.stringContaining("image.gif"), + compressed: expect.stringContaining("webp"), + uncompressed: expect.stringContaining("jpeg"), + }, +} + +describe("Course", () => { + describe("mutations", () => { + beforeAll(() => tmc.setup()) + afterAll(() => tmc.teardown()) + + const getNewCourse = () => ({ + name: "new1", + slug: "new1", + start_date: "01/01/1900", + teacher_in_charge_email: "e@mail.com", + teacher_in_charge_name: "teacher", + study_modules: [{ id: "00000000000000000000000000000101" }], + course_translations: [ + { + description: "description_en_US", + language: "en_US", + name: "name_en_US", + }, + ], + course_variants: [ + { + slug: "variant1", + description: "variant1", + }, + ], + course_aliases: [ + { + course_code: "alias1", + }, + ], + inherit_settings_from: "00000000000000000000000000000002", + completions_handled_by: "00000000000000000000000000000002", + user_course_settings_visibilities: [{ language: "en_US" }], + new_photo: createReadStream(__dirname + "/../../../tests/data/image.gif"), + tags: [ + { + id: "48100000-0000-0000-0000-000000000001", + }, + ], + }) + + const getUpdateCourse = () => ({ + // id: "00000000000000000000000000000002", + name: "updated course1", + slug: "course1", + new_slug: "updated_course1", + start_date: "02/01/1900", + end_date: "12/30/2100", + teacher_in_charge_email: "updated-e@mail.com", + teacher_in_charge_name: "updated teacher", + course_translations: [ + { + id: "00000000-0000-0000-0000-000000000011", + description: "course1_updated_description_en_US", + language: "en_US", + name: "course1_en_US", + link: "http://link.com", + }, + { + description: "course1_added_description_se_SE", + language: "se_SE", + name: "course1_se_SE", + link: "http:/link.se.com", + }, + ], + study_modules: [ + { + id: "00000000-0000-0000-0000-000000000101", + }, + ], + course_variants: [ + { + slug: "variant1", + description: "variant1", + }, + ], + course_aliases: [ + { + course_code: "alias1", + }, + ], + inherit_settings_from: "00000000000000000000000000000001", + completions_handled_by: "00000000000000000000000000000001", + user_course_settings_visibilities: [{ language: "en_US" }], + photo: "00000000000000000000000000001101", + new_photo: createReadStream(__dirname + "/../../../tests/data/image.gif"), + tags: [ + { + id: "48100000-0000-0000-0000-000000000002", + }, + ], + }) + + const expectedAddedCourse = { + photo: { + ...anyPhoto.photo, + }, + } + + const expectedUpdatedCourse = { + id: "00000000-0000-0000-0000-000000000002", + study_modules: [ + { + id: "00000000-0000-0000-0000-000000000101", + }, + ], + } + + type TestCase = [ + string, + { + data: Record + expected: Record + omitIdFields?: Array + }, + ] + + describe("addCourse", () => { + beforeEach(async () => { + await seed(ctx.prisma) + ctx.client.setHeader("Authorization", "Bearer admin") + mocked(KafkaProducer).mockClear() + }) + + const cases: TestCase[] = [ + [ + "full", + { + data: getNewCourse(), + expected: expectedAddedCourse, + }, + ], + [ + "with no course_translations", + { + data: omit(getNewCourse(), "course_translations"), + expected: omit(expectedAddedCourse, "course_translations"), + }, + ], + [ + "with no study_modules", + { + data: omit(getNewCourse(), "study_modules"), + expected: expectedAddedCourse, + }, + ], + [ + "with no photo", + { + data: omit(getNewCourse(), "new_photo"), + expected: omit(expectedAddedCourse, "photo"), + omitIdFields: ["photo_id"], + }, + ], + [ + "with no course tags", + { + data: omit(getNewCourse(), "tags"), + expected: omit(expectedAddedCourse, "tags"), + }, + ], + ] + + test.each(cases)( + "creates a course %s", + async (_, { data, expected, omitIdFields = [] }) => { + const res = await ctx.client.request(createCourseMutation, { + course: data, + }) + + expect(res.addCourse).toMatchStrippedSnapshot(expected) + + expect(KafkaProducer).toHaveBeenCalledTimes(1) + + const createdCourse = await ctx.prisma.course.findUnique({ + where: { slug: "new1" }, + include: courseInclude, + }) + + expect( + mocked(KafkaProducer).mock.instances[0].queueProducerMessage, + ).toHaveBeenCalledWith({ + message: JSON.stringify( + omit(createdCourse, Object.keys(courseInclude)), + ), + partition: null, + topic: "new-course", + }) + + const hasPhoto = Boolean(expected?.photo) + + expect(createdCourse).not.toEqual(null) + expect(createdCourse?.id).toEqual(res.addCourse.id) + expect(createdCourse).toMatchStrippedSnapshot( + { + ...(hasPhoto && { + photo: { + ...anyPhoto.photo, + original: expect.stringContaining("image.gif"), + }, + }), + }, + { + idFields: [ + "id", + "course_id", + /*"course_aliases.course_id", + "course_variants.course_id", + "course_tags.course_id", + "course_translations.course_id",*/ + "photo_id", + ].filter((f) => !omitIdFields.includes(f)), //.filter(isNotNullOrUndefined), + }, + ) + }, + ) + + it("errors with non-admin", async () => { + ctx.client.setHeader("Authorization", "Bearer normal") + try { + await ctx.client.request(createCourseMutation, { + course: getNewCourse(), + }) + fail() + } catch {} + }) + }) + + describe("updateCourse", () => { + beforeEach(async () => { + await seed(ctx.prisma) + ctx.client.setHeader("Authorization", "Bearer admin") + }) + + it("errors on no slug given", async () => { + try { + await ctx.client.request(updateCourseMutation, { + course: omit(getUpdateCourse(), "slug"), + }) + fail() + } catch {} + }) + + it("updates course", async () => { + const res = await ctx.client.request(updateCourseMutation, { + course: { + ...getUpdateCourse(), + new_photo: undefined, + }, + }) + + expect(res.updateCourse).toMatchStrippedSnapshot( + { + ...expectedUpdatedCourse, + photo: { + ...anyPhoto.photo, + original: expect.stringContaining("original.gif"), + }, + }, + { + excludePaths: ["id", "study_modules"], + }, + ) + + const oldCourse = await ctx.prisma.course.findUnique({ + where: { slug: "course1" }, + include: courseInclude, + }) + expect(oldCourse).toBeNull() + const updatedCourse = await ctx.prisma.course.findUnique({ + where: { slug: "updated_course1" }, + include: courseInclude, + }) + expect(updatedCourse).toMatchStrippedSnapshot( + { + ...anyPhoto, + photo: { + ...anyPhoto.photo, + original: expect.stringContaining("original.gif"), + }, + }, + { + excludePaths: ["id", "study_modules"], + }, + ) + }) + + it("updates photo", async () => { + const res = await ctx.client.request(updateCourseMutation, { + course: getUpdateCourse(), + }) + + expect(res.updateCourse).toMatchStrippedSnapshot( + { + photo: { + ...anyPhoto.photo, + }, + }, + { + excludePaths: ["id", "study_modules"], + }, + ) + + const oldCourse = await ctx.prisma.course.findUnique({ + where: { slug: "course1" }, + include: courseInclude, + }) + expect(oldCourse).toBeNull() + const oldImage = await ctx.prisma.image.findUnique({ + where: { id: "00000000000000000000000000001101" }, + }) + expect(oldImage).toBeNull() + + const updatedCourse = await ctx.prisma.course.findUnique({ + where: { slug: "updated_course1" }, + include: courseInclude, + }) + expect(updatedCourse).toMatchStrippedSnapshot({ + ...anyPhoto, + photo_id: expect.not.stringContaining( + "00000000000000000000000000001101", + ), + }) + }) + + it("deletes photo", async () => { + const res = await ctx.client.request(updateCourseMutation, { + course: { + ...getUpdateCourse(), + new_photo: undefined, + new_slug: undefined, + delete_photo: true, + }, + }) + + expect(res.updateCourse).toMatchStrippedSnapshot({ + ...expectedUpdatedCourse, + photo: null, + }) + const updatedCourse = await ctx.prisma.course.findUnique({ + where: { slug: "course1" }, + include: courseInclude, + }) + expect(updatedCourse).toMatchStrippedSnapshot() + }) + + it("errors with non-admin", async () => { + ctx.client.setHeader("Authorization", "Bearer normal") + try { + await ctx.client.request(updateCourseMutation, { + course: getUpdateCourse(), + }) + fail() + } catch {} + }) + }) + + describe("deleteCourse", () => { + beforeEach(async () => { + await seed(ctx.prisma) + ctx.client.setHeader("Authorization", "Bearer admin") + }) + + it("deletes course on id", async () => { + const res = await ctx.client.request(deleteCourseMutation, { + id: "00000000000000000000000000000002", + }) + + expect(res).toMatchSnapshot() + const deletedCourse = await ctx.prisma.course.findUnique({ + where: { id: "00000000000000000000000000000002" }, + }) + expect(deletedCourse).toBeNull() + const deletedImage = await ctx.prisma.image.findUnique({ + where: { id: "00000000000000000000000000001101" }, + }) + expect(deletedImage).toBeNull() + }) + + it("deletes course on slug", async () => { + const res = await ctx.client.request(deleteCourseMutation, { + slug: "course1", + }) + + expect(res).toMatchSnapshot() + const deletedCourse = await ctx.prisma.course.findUnique({ + where: { slug: "course1" }, + }) + expect(deletedCourse).toBeNull() + }) + + it("errors with non-admin", async () => { + ctx.client.setHeader("Authorization", "Bearer normal") + try { + await ctx.client.request(deleteCourseMutation, { + slug: "course1", + }) + fail() + } catch {} + }) + }) + }) +}) + +const createCourseMutation = gql` + mutation createCourse($course: CourseCreateArg!) { + addCourse(course: $course) { + id + name + slug + ects + order + study_module_order + teacher_in_charge_name + teacher_in_charge_email + support_email + start_date + end_date + tier + photo { + id + original + compressed + compressed_mimetype + uncompressed + uncompressed_mimetype + } + promote + start_point + hidden + study_module_start_point + status + course_translations { + id + name + language + description + link + } + open_university_registration_links { + id + course_code + language + link + } + study_modules { + id + } + course_variants { + id + slug + description + } + course_aliases { + id + course_code + } + inherit_settings_from { + id + } + completions_handled_by { + id + } + has_certificate + user_course_settings_visibilities { + id + language + } + upcoming_active_link + automatic_completions + automatic_completions_eligible_for_ects + exercise_completions_needed + points_needed + tags { + id + hidden + types + tag_translations { + name + description + language + } + } + } + } +` + +const updateCourseMutation = gql` + mutation updateCourse($course: CourseUpsertArg!) { + updateCourse(course: $course) { + id + name + slug + ects + order + study_module_order + teacher_in_charge_name + teacher_in_charge_email + support_email + start_date + end_date + tier + photo { + id + original + compressed + compressed_mimetype + uncompressed + uncompressed_mimetype + } + promote + start_point + hidden + study_module_start_point + status + course_translations { + id + name + language + description + link + } + open_university_registration_links { + id + course_code + language + link + } + study_modules { + id + } + course_variants { + id + slug + description + } + course_aliases { + id + course_code + } + inherit_settings_from { + id + } + completions_handled_by { + id + } + has_certificate + user_course_settings_visibilities { + id + language + } + upcoming_active_link + automatic_completions + automatic_completions_eligible_for_ects + exercise_completions_needed + points_needed + tags { + id + hidden + types + tag_translations { + name + description + language + } + } + } + } +` + +const deleteCourseMutation = gql` + mutation deleteCourse($id: ID, $slug: String) { + deleteCourse(id: $id, slug: $slug) { + id + } + } +` diff --git a/backend/graphql/Course/__test__/Course.queries.test.ts b/backend/graphql/Course/__test__/Course.queries.test.ts new file mode 100644 index 000000000..aac010a4f --- /dev/null +++ b/backend/graphql/Course/__test__/Course.queries.test.ts @@ -0,0 +1,493 @@ +import { gql } from "graphql-request" +import { get, orderBy } from "lodash" + +import { Course } from "@prisma/client" + +import { fakeTMCCurrent, getTestContext, ID_REGEX } from "../../../tests" +import { adminUserDetails, normalUserDetails } from "../../../tests/data" +import { seed } from "../../../tests/data/seed" + +jest.mock("../../../services/kafkaProducer") + +const ctx = getTestContext() +const tmc = fakeTMCCurrent({ + "Bearer normal": [200, normalUserDetails], + "Bearer admin": [200, adminUserDetails], +}) + +describe("Course", () => { + describe("queries", () => { + beforeAll(() => tmc.setup()) + afterAll(() => tmc.teardown()) + + describe("course", () => { + let createdCourses: Course[] | null = null + + beforeEach(async () => { + createdCourses = (await seed(ctx.prisma)).courses + }) + + afterEach(() => (createdCourses = null)) + + describe("normal user", () => { + beforeEach(() => ctx.client.setHeader("Authorization", "Bearer normal")) + + it("should error on no parameters", async () => { + try { + await ctx.client.request(courseQuery) + fail() + } catch {} + }) + + it("returns course on id and slug", async () => { + const resId = await ctx.client.request(courseQuery, { + id: createdCourses?.[0].id, + }) + const resSlug = await ctx.client.request(courseQuery, { + slug: "course1", + }) + + ;[resId, resSlug].forEach((res) => + // had sortStudyModules + expect(res.course).toMatchSnapshot({ + id: expect.stringMatching(ID_REGEX), + }), + ) + }) + + it("returns correct language", async () => { + const res = await ctx.client.request(courseQuery, { + slug: "course1", + language: "en_US", + }) + + // had sortStudyModules + expect(res.course).toMatchSnapshot({ + id: expect.stringMatching(ID_REGEX), + }) + }) + + it("should return null on non-existent language", async () => { + const res = await ctx.client.request(courseQuery, { + slug: "course1", + language: "sv_SE", + }) + + expect(res).toEqual({ course: null }) + }) + + it("should error on invalid id and slug", async () => { + try { + await ctx.client.request(courseQuery, { + id: new Array(33).join("1"), + }) + fail() + } catch {} + try { + await ctx.client.request(courseQuery, { + slug: "invalid", + }) + fail() + } catch {} + }) + }) + + describe("admin", () => { + beforeEach(() => ctx.client.setHeader("Authorization", "Bearer admin")) + + it("returns full course on id and slug", async () => { + const resId = await ctx.client.request(fullCourseQuery, { + id: createdCourses?.[0].id, + }) + const resSlug = await ctx.client.request(fullCourseQuery, { + slug: "course1", + }) + + ;[resId, resSlug].forEach((res) => + expect( + applySortFns([sortExercises, sortStudyModules, sortTags])( + res.course, + ), + ).toMatchSnapshot({ + id: expect.stringMatching(ID_REGEX), + }), + ) + }) + + it("should include deleted exercises if specified", async () => { + const res = await ctx.client.request(fullCourseQuery, { + slug: "course1", + includeDeletedExercises: true, + }) + + expect( + applySortFns([sortExercises, sortStudyModules, sortTags])( + res.course, + ), + ).toMatchSnapshot() + }) + }) + }) + + describe("courses", () => { + beforeEach(async () => { + await seed(ctx.prisma) + }) + + it("returns courses", async () => { + const res = await ctx.client.request(coursesQuery) + + expect( + orderBy(res.courses.map(sortStudyModules), ["id"]), + ).toMatchSnapshot() + }) + + it("returns courses ordered", async () => { + for (const order of ["asc", "desc"]) { + const res = await ctx.client.request(coursesQuery, { + orderBy: { name: order }, + }) + + expect(res.courses.map(sortStudyModules)).toMatchSnapshot( + `courses-order-${order}`, + ) + } + }) + + it("returns courses filtered by language", async () => { + for (const language of ["fi_FI", "en_US", "bogus"]) { + const res = await ctx.client.request(coursesQuery, { + language, + }) + + expect( + orderBy(res.courses?.map(sortStudyModules), ["id"]), + ).toMatchSnapshot(`courses-language-${language}`) + } + }) + + const searchTest: Array<[string, string[]]> = [ + ["course1", ["course1"]], + ["teacher", ["course1", "course2"]], + ["teacher1", ["course1"]], + ["teacher2", ["course2"]], + ["teacher3", []], + ["e@mail", ["course1", "course2"]], + ["en_US", ["course1"]], + ["se_SE", []], + ] + + it("returns search results", async () => { + for (const [search, expected] of searchTest) { + const res = await ctx.client.request(coursesQuery, { + search, + }) + + const resultSlugs = res.courses?.map((c: Course) => c.slug).sort() + + expect(resultSlugs).toEqual(expected.sort()) + } + }) + + it("filters hidden", async () => { + for (const hidden of [true, false, null]) { + const res = await ctx.client.request(coursesQuery, { + hidden, + }) + + expect(res.courses?.map((c: Course) => c.id).sort()).toMatchSnapshot( + `courses-hidden-${hidden}`, + ) + } + }) + + it("filters handledBy", async () => { + for (const handledBy of ["handler", "foo"]) { + const res = await ctx.client.request(coursesQuery, { + handledBy, + }) + + expect(res.courses?.map((c: Course) => c.id).sort()).toMatchSnapshot( + `courses-hidden-${handledBy}`, + ) + } + }) + }) + + describe("course_exists", () => { + beforeEach(async () => { + await seed(ctx.prisma) + ctx.client.setHeader("Authorization", "Bearer normal") + }) + + it("returns true on existing course", async () => { + const res = await ctx.client.request(courseExistsQuery, { + slug: "course1", + }) + + expect(res).toEqual({ course_exists: true }) + }) + + it("returns false on non-existing course", async () => { + const res = await ctx.client.request(courseExistsQuery, { + slug: "bogus", + }) + + expect(res).toEqual({ course_exists: false }) + }) + }) + + describe("handlerCourses", () => { + beforeEach(async () => { + await seed(ctx.prisma) + }) + + it("returns correctly", async () => { + const res = await ctx.client.request( + handlerCoursesQuery, + {}, + { + Authorization: "Bearer admin", + }, + ) + + expect(res.handlerCourses).toMatchSnapshot() + }) + + it("errors with non-admin", async () => { + try { + await ctx.client.request( + handlerCoursesQuery, + {}, + { + Authorization: "Bearer normal", + }, + ) + fail() + } catch {} + }) + }) + }) +}) + +const courseQuery = gql` + query course($id: ID, $slug: String, $language: String) { + course(id: $id, slug: $slug, language: $language) { + id + name + slug + description + link + } + } +` + +const fullCourseQuery = gql` + query course( + $id: ID + $slug: String + $language: String + $includeDeletedExercises: Boolean + ) { + course(id: $id, slug: $slug, language: $language) { + id + name + slug + ects + order + study_module_order + teacher_in_charge_name + teacher_in_charge_email + support_email + start_date + end_date + tier + photo { + id + compressed + compressed_mimetype + uncompressed + uncompressed_mimetype + } + promote + start_point + hidden + study_module_start_point + status + course_translations { + id + name + language + description + link + } + open_university_registration_links { + id + course_code + language + link + } + study_modules { + id + } + course_variants { + id + slug + description + } + course_aliases { + id + course_code + } + inherit_settings_from { + id + } + completions_handled_by { + id + } + has_certificate + user_course_settings_visibilities { + id + language + } + exercises(includeDeleted: $includeDeletedExercises) { + id + name + deleted + } + upcoming_active_link + automatic_completions + automatic_completions_eligible_for_ects + exercise_completions_needed + points_needed + tags(language: $language) { + id + hidden + name + description + types + tag_types { + name + } + tag_translations { + language + name + description + } + } + } + } +` + +const coursesQuery = gql` + query AllCourses( + $language: String + $orderBy: CourseOrderByWithRelationInput + $search: String + $hidden: Boolean + $handledBy: String + ) { + courses( + orderBy: $orderBy + language: $language + search: $search + hidden: $hidden + handledBy: $handledBy + ) { + id + slug + name + order + study_module_order + photo { + id + compressed + uncompressed + } + promote + status + start_point + study_module_start_point + hidden + description + link + upcoming_active_link + study_modules { + id + slug + } + course_translations { + id + language + name + } + user_course_settings_visibilities { + id + language + } + tags(language: $language) { + id + hidden + name + description + types + } + } + } +` + +const courseExistsQuery = gql` + query courseExists($slug: String!) { + course_exists(slug: $slug) + } +` + +const handlerCoursesQuery = gql` + query handlerCourses { + handlerCourses { + id + handles_completions_for { + id + } + } + } +` + +const sortArrayField = + (field: string, id: Array = ["id"]) => + (object: any) => { + if (!get(object, field)) { + return object + } + + return { + ...object, + [field]: orderBy(get(object, field), id, ["asc"]), + } + } +// study_modules may be returned in any order, let's just sort them so snapshots are equal + +const sortStudyModules = sortArrayField("study_modules") +const sortExercises = sortArrayField("exercises") +const sortTags = (course: any) => + sortArrayField("tags")({ + ...course, + tags: course?.tags.map((tag: any) => ({ + ...tag, + ...(tag.types && { types: orderBy(tag.types) }), + ...(tag.tag_types && { + tag_types: sortArrayField("tag_types", ["name"])(tag).tag_types, + }), + ...(tag.tag_translations && { + tag_translations: sortArrayField("tag_translations", [ + "language", + "name", + "description", + ])(tag).tag_translations, + }), + })), + }) + +const applySortFns = (sortFns: Array<(course: T) => T>) => (course: any) => { + return sortFns.reduce((course, fn) => fn(course), course) +} diff --git a/backend/graphql/Course/__test__/Course.test.ts b/backend/graphql/Course/__test__/Course.test.ts index ab8ebf2db..66931f891 100644 --- a/backend/graphql/Course/__test__/Course.test.ts +++ b/backend/graphql/Course/__test__/Course.test.ts @@ -1,14 +1,9 @@ -import { createReadStream } from "fs" - import { gql } from "graphql-request" -import { mocked } from "jest-mock" -import { omit, orderBy } from "lodash" - -import { Course } from "@prisma/client" +import { orderBy } from "lodash" -import KafkaProducer from "../../../services/kafkaProducer" import { fakeTMCCurrent, getTestContext } from "../../../tests" -import { adminUserDetails, normalUserDetails, seed } from "../../../tests/data" +import { adminUserDetails, normalUserDetails } from "../../../tests/data" +import { seed } from "../../../tests/data/seed" jest.mock("../../../services/kafkaProducer") @@ -18,156 +13,6 @@ const tmc = fakeTMCCurrent({ "Bearer admin": [200, adminUserDetails], }) -const courseQuery = gql` - query course($id: ID, $slug: String, $language: String) { - course(id: $id, slug: $slug, language: $language) { - id - name - slug - description - link - } - } -` - -const fullCourseQuery = gql` - query course( - $id: ID - $slug: String - $language: String - $includeDeletedExercises: Boolean - ) { - course(id: $id, slug: $slug, language: $language) { - id - name - slug - ects - order - study_module_order - teacher_in_charge_name - teacher_in_charge_email - support_email - start_date - end_date - tier - photo { - id - compressed - compressed_mimetype - uncompressed - uncompressed_mimetype - } - promote - start_point - hidden - study_module_start_point - status - course_translations { - id - name - language - description - link - } - open_university_registration_links { - id - course_code - language - link - } - study_modules { - id - } - course_variants { - id - slug - description - } - course_aliases { - id - course_code - } - inherit_settings_from { - id - } - completions_handled_by { - id - } - has_certificate - user_course_settings_visibilities { - id - language - } - exercises(includeDeleted: $includeDeletedExercises) { - id - name - deleted - } - upcoming_active_link - automatic_completions - automatic_completions_eligible_for_ects - exercise_completions_needed - points_needed - } - } -` - -const coursesQuery = gql` - query AllCourses( - $language: String - $orderBy: CourseOrderByInput - $search: String - $hidden: Boolean - $handledBy: String - ) { - courses( - orderBy: $orderBy - language: $language - search: $search - hidden: $hidden - handledBy: $handledBy - ) { - id - slug - name - order - study_module_order - photo { - id - compressed - uncompressed - } - promote - status - start_point - study_module_start_point - hidden - description - link - upcoming_active_link - study_modules { - id - slug - } - course_translations { - id - language - name - } - user_course_settings_visibilities { - id - language - } - } - } -` - -const courseExistsQuery = gql` - query courseExists($slug: String!) { - course_exists(slug: $slug) - } -` - const courseCompletionsQuery = gql` query courseCompletions( $slug: String @@ -190,194 +35,37 @@ const courseCompletionsQuery = gql` } ` -const createCourseMutation = gql` - mutation createCourse($course: CourseCreateArg!) { - addCourse(course: $course) { - id - name - slug - ects - order - study_module_order - teacher_in_charge_name - teacher_in_charge_email - support_email - start_date - end_date - tier - photo { - id - original - compressed - compressed_mimetype - uncompressed - uncompressed_mimetype - } - promote - start_point - hidden - study_module_start_point - status - course_translations { - id - name - language - description - link - } - open_university_registration_links { - id - course_code - language - link - } - study_modules { - id - } - course_variants { - id - slug - description - } - course_aliases { - id - course_code - } - inherit_settings_from { - id - } - completions_handled_by { - id - } - has_certificate - user_course_settings_visibilities { - id - language - } - upcoming_active_link - automatic_completions - automatic_completions_eligible_for_ects - exercise_completions_needed - points_needed - } - } -` - -const updateCourseMutation = gql` - mutation updateCourse($course: CourseUpsertArg!) { - updateCourse(course: $course) { +const courseTagsQuery = gql` + query courseTags( + $slug: String + $language: String + $types: [String!] + $search: String + $includeHidden: Boolean + ) { + course(slug: $slug, language: $language) { id - name - slug - ects - order - study_module_order - teacher_in_charge_name - teacher_in_charge_email - support_email - start_date - end_date - tier - photo { - id - original - compressed - compressed_mimetype - uncompressed - uncompressed_mimetype - } - promote - start_point - hidden - study_module_start_point - status - course_translations { + tags( + language: $language + types: $types + search: $search + includeHidden: $includeHidden + ) { id name - language - description - link - } - open_university_registration_links { - id - course_code - language - link - } - study_modules { - id - } - course_variants { - id - slug description - } - course_aliases { - id - course_code - } - inherit_settings_from { - id - } - completions_handled_by { - id - } - has_certificate - user_course_settings_visibilities { - id - language - } - upcoming_active_link - automatic_completions - automatic_completions_eligible_for_ects - exercise_completions_needed - points_needed - } - } -` - -const deleteCourseMutation = gql` - mutation deleteCourse($id: ID, $slug: String) { - deleteCourse(id: $id, slug: $slug) { - id - } - } -` - -const handlerCoursesQuery = gql` - query handlerCourses { - handlerCourses { - id - handles_completions_for { - id + hidden + types + tag_translations { + language + name + description + } } } } ` -// study_modules may be returned in any order, let's just sort them so snapshots are equal -const sortStudyModules = (course: any) => { - if (!course?.study_modules) { - return course - } - - return { - ...course, - study_modules: orderBy(course.study_modules, ["id"], ["asc"]), - } -} - -const sortExercises = (course: any) => { - if (!course?.exercises) { - return course - } - - return { - ...course, - exercises: orderBy(course.exercises, ["id"]), - } -} - describe("Course", () => { afterAll(() => jest.clearAllMocks()) @@ -485,637 +173,124 @@ describe("Course", () => { }).toMatchSnapshot() }) }) - }) - - describe("queries", () => { - beforeAll(() => tmc.setup()) - afterAll(() => tmc.teardown()) - - describe("course", () => { - let createdCourses: Course[] | null = null + describe("tags", () => { beforeEach(async () => { - createdCourses = (await seed(ctx.prisma)).courses + await seed(ctx.prisma) }) - afterEach(() => (createdCourses = null)) - describe("normal user", () => { - beforeEach(() => ctx.client.setHeader("Authorization", "Bearer normal")) - - it("should error on no parameters", async () => { - try { - await ctx.client.request(courseQuery) - fail() - } catch {} - }) - - it("returns course on id and slug", async () => { - const resId = await ctx.client.request(courseQuery, { - id: createdCourses?.[0].id, - }) - const resSlug = await ctx.client.request(courseQuery, { - slug: "course1", - }) - - ;[resId, resSlug].map((res) => - // had sortStudyModules - expect(res.course).toMatchSnapshot({ - id: expect.any(String), - }), - ) - }) - - it("returns correct language", async () => { - const res = await ctx.client.request(courseQuery, { - slug: "course1", - language: "en_US", - }) - - // had sortStudyModules - expect(res.course).toMatchSnapshot({ - id: expect.any(String), - }) - }) - - it("should return null on non-existent language", async () => { - const res = await ctx.client.request(courseQuery, { - slug: "course1", - language: "sv_SE", - }) - - expect(res).toEqual({ course: null }) - }) - - it("should error on invalid id and slug", async () => { - try { - await ctx.client.request(courseQuery, { - id: new Array(33).join("1"), - }) - fail() - } catch {} + it("should error when includeHidden provided", async () => { try { - await ctx.client.request(courseQuery, { - slug: "invalid", - }) - fail() - } catch {} - }) - }) - - describe("admin", () => { - beforeEach(() => ctx.client.setHeader("Authorization", "Bearer admin")) - - it("returns full course on id and slug", async () => { - const resId = await ctx.client.request(fullCourseQuery, { - id: createdCourses?.[0].id, - }) - const resSlug = await ctx.client.request(fullCourseQuery, { - slug: "course1", - }) - - ;[resId, resSlug].map((res) => - expect(sortExercises(sortStudyModules(res.course))).toMatchSnapshot( + await ctx.client.request( + courseTagsQuery, { - id: expect.any(String), + slug: "course1", + includeHidden: true, }, - ), - ) - }) - - it("should include deleted exercises if specified", async () => { - const res = await ctx.client.request(fullCourseQuery, { - slug: "course1", - includeDeletedExercises: true, - }) - - expect(sortExercises(sortStudyModules(res.course))).toMatchSnapshot() + { + Authorization: "Bearer normal", + }, + ) + fail() + } catch (e: any) { + expect(e.response.errors?.length).toBe(1) + } }) - }) - }) - - describe("courses", () => { - beforeEach(async () => { - await seed(ctx.prisma) - }) - - it("returns courses", async () => { - const res = await ctx.client.request(coursesQuery) - - expect( - orderBy(res.courses.map(sortStudyModules), ["id"]), - ).toMatchSnapshot() - }) - - it("returns courses ordered", async () => { - for (const order of ["asc", "desc"]) { - const res = await ctx.client.request(coursesQuery, { - orderBy: { name: order }, - }) - expect(res.courses.map(sortStudyModules)).toMatchSnapshot( - `courses-order-${order}`, - ) - } - }) - - it("returns courses filtered by language", async () => { - for (const language of ["fi_FI", "en_US", "bogus"]) { - const res = await ctx.client.request(coursesQuery, { - language, - }) - - expect( - orderBy(res.courses?.map(sortStudyModules), ["id"]), - ).toMatchSnapshot(`courses-language-${language}`) - } - }) - - const searchTest: Array<[string, string[]]> = [ - ["course1", ["course1"]], - ["teacher", ["course1", "course2"]], - ["teacher1", ["course1"]], - ["teacher2", ["course2"]], - ["teacher3", []], - ["e@mail", ["course1", "course2"]], - ["en_US", ["course1"]], - ["se_SE", []], - ] - - it("returns search results", async () => { - for (const [search, expected] of searchTest) { - const res = await ctx.client.request(coursesQuery, { - search, - }) - - const resultSlugs = res.courses?.map((c: Course) => c.slug).sort() - - expect(resultSlugs).toEqual(expected.sort()) - } - }) - - it("filters hidden", async () => { - for (const hidden of [true, false, null]) { - const res = await ctx.client.request(coursesQuery, { - hidden, - }) - - expect(res.courses?.map((c: Course) => c.id).sort()).toMatchSnapshot( - `courses-hidden-${hidden}`, + it("should return name and description in root when language provided", async () => { + const res = await ctx.client.request( + courseTagsQuery, + { + slug: "course1", + language: "en_US", + }, + { + Authorization: "Bearer normal", + }, ) - } - }) - it("filters handledBy", async () => { - for (const handledBy of ["handler", "foo"]) { - const res = await ctx.client.request(coursesQuery, { - handledBy, - }) + const received = res.course?.tags?.sort() - expect(res.courses?.map((c: Course) => c.id).sort()).toMatchSnapshot( - `courses-hidden-${handledBy}`, + expect(received.length).toBe(2) + expect(received[0].name).toBe("tag1 in english") + expect(received[0].description).toBe("tag1 description") + expect(received[0].types).toContain("type1") + expect(received[1].name).toBe("tag2 in english") + expect(received[1].description).toBe("tag2 description") + expect(received[1].types).toEqual( + expect.arrayContaining(["type1", "type2"]), ) - } - }) - }) - - describe("course_exists", () => { - beforeEach(async () => { - await seed(ctx.prisma) - ctx.client.setHeader("Authorization", "Bearer normal") - }) - - it("returns true on existing course", async () => { - const res = await ctx.client.request(courseExistsQuery, { - slug: "course1", - }) - - expect(res).toEqual({ course_exists: true }) - }) - - it("returns false on non-existing course", async () => { - const res = await ctx.client.request(courseExistsQuery, { - slug: "bogus", - }) - - expect(res).toEqual({ course_exists: false }) - }) - }) - - describe("handlerCourses", () => { - beforeEach(async () => { - await seed(ctx.prisma) - ctx.client.setHeader("Authorization", "Bearer admin") - }) - - it("returns correctly", async () => { - const res = await ctx.client.request(handlerCoursesQuery) - - expect(res.handlerCourses).toMatchSnapshot() - }) - - it("errors with non-admin", async () => { - ctx.client.setHeader("Authorization", "Bearer normal") - try { - await ctx.client.request(handlerCoursesQuery) - fail() - } catch {} - }) - }) - }) - - describe("mutations", () => { - beforeAll(() => tmc.setup()) - afterAll(() => tmc.teardown()) - - const getNewCourse = () => ({ - name: "new1", - slug: "new1", - start_date: "01/01/1900", - teacher_in_charge_email: "e@mail.com", - teacher_in_charge_name: "teacher", - study_modules: [{ id: "00000000000000000000000000000101" }], - course_translations: [ - { - description: "description_en_US", - language: "en_US", - name: "name_en_US", - }, - ], - course_variants: [ - { - slug: "variant1", - description: "variant1", - }, - ], - course_aliases: [ - { - course_code: "alias1", - }, - ], - inherit_settings_from: "00000000000000000000000000000002", - completions_handled_by: "00000000000000000000000000000002", - user_course_settings_visibilities: [{ language: "en_US" }], - new_photo: createReadStream(__dirname + "/../../../tests/data/image.gif"), - }) - - const getUpdateCourse = () => ({ - // id: "00000000000000000000000000000002", - name: "updated course1", - slug: "course1", - new_slug: "updated_course1", - start_date: "02/01/1900", - end_date: "12/30/2100", - teacher_in_charge_email: "updated-e@mail.com", - teacher_in_charge_name: "updated teacher", - course_translations: [ - { - id: "00000000-0000-0000-0000-000000000011", - description: "course1_updated_description_en_US", - language: "en_US", - name: "course1_en_US", - link: "http://link.com", - }, - { - description: "course1_added_description_se_SE", - language: "se_SE", - name: "course1_se_SE", - link: "http:/link.se.com", - }, - ], - study_modules: [ - { - id: "00000000-0000-0000-0000-000000000101", - }, - ], - course_variants: [ - { - slug: "variant1", - description: "variant1", - }, - ], - course_aliases: [ - { - course_code: "alias1", - }, - ], - inherit_settings_from: "00000000000000000000000000000001", - completions_handled_by: "00000000000000000000000000000001", - user_course_settings_visibilities: [{ language: "en_US" }], - photo: "00000000000000000000000000001101", - new_photo: createReadStream(__dirname + "/../../../tests/data/image.gif"), - }) - - const expectedAddedCourse = { - id: expect.any(String), - course_translations: [ - { - id: expect.any(String), - }, - ], - course_variants: [ - { - id: expect.any(String), - }, - ], - course_aliases: [ - { - id: expect.any(String), - }, - ], - photo: { - original: expect.stringContaining("image.gif"), - compressed: expect.stringContaining("webp"), - uncompressed: expect.stringContaining("jpeg"), - id: expect.any(String), - }, - user_course_settings_visibilities: [ - { - id: expect.any(String), - }, - ], - } - - const expectedUpdatedCourse = { - id: "00000000-0000-0000-0000-000000000002", - study_modules: [ - { - id: expect.stringMatching("00000000-0000-0000-0000-000000000101"), - }, - ], - course_translations: [ - { - id: expect.any(String), - }, - { - id: expect.any(String), - }, - ], - course_variants: [ - { - id: expect.any(String), - }, - ], - course_aliases: [ - { - id: expect.any(String), - }, - ], - photo: { - original: expect.stringContaining("image.gif"), - compressed: expect.stringContaining("webp"), - uncompressed: expect.stringContaining("jpeg"), - id: expect.any(String), - }, - user_course_settings_visibilities: [ - { - id: expect.any(String), - }, - ], - } - - type TestCase = [ - string, - { - data: object - expected: object - }, - ] - - describe("addCourse", () => { - beforeEach(async () => { - await seed(ctx.prisma) - ctx.client.setHeader("Authorization", "Bearer admin") - mocked(KafkaProducer).mockClear() - }) - - const cases: TestCase[] = [ - [ - "full", - { - data: getNewCourse(), - expected: expectedAddedCourse, - }, - ], - [ - "with no course_translations", - { - data: omit(getNewCourse(), "course_translations"), - expected: omit(expectedAddedCourse, "course_translations"), - }, - ], - [ - "with no study_modules", - { - data: omit(getNewCourse(), "study_modules"), - expected: expectedAddedCourse, - }, - ], - [ - "with no photo", - { - data: omit(getNewCourse(), "new_photo"), - expected: omit(expectedAddedCourse, "photo"), - }, - ], - ] - - test.each(cases)("creates a course %s", async (_, { data, expected }) => { - const res = await ctx.client.request(createCourseMutation, { - course: data, - }) - - expect(res).toMatchSnapshot({ - addCourse: expected, - }) - - expect(KafkaProducer).toHaveBeenCalledTimes(1) - - const createdCourse = await ctx.prisma.course.findFirst({ - where: { slug: "new1" }, - }) - expect( - mocked(KafkaProducer).mock.instances[0].queueProducerMessage, - ).toHaveBeenCalledWith({ - message: JSON.stringify(createdCourse), - partition: null, - topic: "new-course", + expect(received[1].types.length).toEqual(2) }) - expect(createdCourse).toBeDefined() - expect(createdCourse?.id).toEqual(res.addCourse.id) - expect(createdCourse).toMatchSnapshot({ - created_at: expect.any(Date), - updated_at: expect.any(Date), - id: expect.any(String), - photo_id: (expected as any).photo ? expect.any(String) : null, - }) - }) - - it("errors with non-admin", async () => { - ctx.client.setHeader("Authorization", "Bearer normal") - try { - await ctx.client.request(createCourseMutation, { - course: getNewCourse(), - }) - fail() - } catch {} - }) - }) - - describe("updateCourse", () => { - beforeEach(async () => { - await seed(ctx.prisma) - ctx.client.setHeader("Authorization", "Bearer admin") - }) - - it("errors on no slug given", async () => { - try { - await ctx.client.request(updateCourseMutation, { - course: omit(getUpdateCourse(), "slug"), - }) - fail() - } catch {} - }) - - it("updates course", async () => { - const res = await ctx.client.request(updateCourseMutation, { - course: { - ...getUpdateCourse(), - new_photo: undefined, - }, - }) - - expect(res).toMatchSnapshot({ - updateCourse: { - ...expectedUpdatedCourse, - photo: { - ...expectedUpdatedCourse.photo, - original: expect.stringContaining("original.gif"), + it("should not return hidden tags", async () => { + const res = await ctx.client.request( + courseTagsQuery, + { + slug: "course2", + language: "fi_FI", }, - }, - }) - - const oldCourse = await ctx.prisma.course.findFirst({ - where: { slug: "course1" }, - }) - expect(oldCourse).toBeNull() - const updatedCourse = await ctx.prisma.course.findFirst({ - where: { slug: "updated_course1" }, - }) - expect(updatedCourse).toMatchSnapshot({ - created_at: expect.any(Date), - updated_at: expect.any(Date), - photo_id: expect.any(String), - }) - }) - - it("updates photo", async () => { - const res = await ctx.client.request(updateCourseMutation, { - course: getUpdateCourse(), - }) - - expect(res).toMatchSnapshot({ - updateCourse: expectedUpdatedCourse, - }) + { + Authorization: "Bearer normal", + }, + ) - const oldCourse = await ctx.prisma.course.findFirst({ - where: { slug: "course1" }, - }) - expect(oldCourse).toBeNull() - const oldImage = await ctx.prisma.image.findFirst({ - where: { id: "00000000000000000000000000001101" }, + expect(res.course?.tags?.length).toBe(0) }) - expect(oldImage).toBeNull() - const updatedCourse = await ctx.prisma.course.findFirst({ - where: { slug: "updated_course1" }, - }) - expect(updatedCourse).toMatchSnapshot({ - created_at: expect.any(Date), - updated_at: expect.any(Date), - photo_id: expect.any(String), - }) - }) - - it("deletes photo", async () => { - const res = await ctx.client.request(updateCourseMutation, { - course: { - ...getUpdateCourse(), - new_photo: undefined, - new_slug: undefined, - delete_photo: true, - }, - }) + it("should only return search matches", async () => { + const res = await ctx.client.request( + courseTagsQuery, + { + slug: "course1", + language: "fi_FI", + search: "mUuTa", + }, + { + Authorization: "Bearer normal", + }, + ) - expect(res).toMatchSnapshot({ - updateCourse: { - ...expectedUpdatedCourse, - photo: null, - }, - }) - const updatedCourse = await ctx.prisma.course.findFirst({ - where: { slug: "course1" }, - }) - expect(updatedCourse).toMatchSnapshot({ - created_at: expect.any(Date), - updated_at: expect.any(Date), + expect(res.course?.tags?.length).toBe(1) + expect(res.course?.tags[0].name).toBe("tag2 suomeksi") }) - }) - - it("errors with non-admin", async () => { - ctx.client.setHeader("Authorization", "Bearer normal") - try { - await ctx.client.request(updateCourseMutation, { - course: getUpdateCourse(), - }) - fail() - } catch {} - }) - }) - - describe("deleteCourse", () => { - beforeEach(async () => { - await seed(ctx.prisma) - ctx.client.setHeader("Authorization", "Bearer admin") - }) - it("deletes course on id", async () => { - const res = await ctx.client.request(deleteCourseMutation, { - id: "00000000000000000000000000000002", - }) + it("should only return chosen types", async () => { + const res = await ctx.client.request( + courseTagsQuery, + { + slug: "course1", + language: "fi_FI", + types: ["type2"], + }, + { + Authorization: "Bearer normal", + }, + ) - expect(res).toMatchSnapshot() - const deletedCourse = await ctx.prisma.course.findFirst({ - where: { id: "00000000000000000000000000000002" }, + expect(res.course?.tags?.length).toBe(1) + expect(res.course?.tags[0].name).toBe("tag2 suomeksi") }) - expect(deletedCourse).toBeNull() - const deletedImage = await ctx.prisma.image.findFirst({ - where: { id: "00000000000000000000000000001101" }, - }) - expect(deletedImage).toBeNull() }) - it("deletes course on slug", async () => { - const res = await ctx.client.request(deleteCourseMutation, { - slug: "course1", - }) + describe("admin", () => { + it("should return hidden tags", async () => { + const res = await ctx.client.request( + courseTagsQuery, + { + slug: "course2", + language: "fi_FI", + includeHidden: true, + }, + { + Authorization: "Bearer admin", + }, + ) - expect(res).toMatchSnapshot() - const deletedCourse = await ctx.prisma.course.findFirst({ - where: { slug: "course1" }, + expect(res.course?.tags?.length).toBe(1) + expect(res.course?.tags[0].name).toBe("piilotettu tag3") }) - expect(deletedCourse).toBeNull() - }) - - it("errors with non-admin", async () => { - ctx.client.setHeader("Authorization", "Bearer normal") - try { - await ctx.client.request(deleteCourseMutation, { - slug: "course1", - }) - fail() - } catch {} }) }) }) diff --git a/backend/graphql/Course/__test__/__snapshots__/Course.mutations.test.ts.snap b/backend/graphql/Course/__test__/__snapshots__/Course.mutations.test.ts.snap new file mode 100644 index 000000000..90f18fb77 --- /dev/null +++ b/backend/graphql/Course/__test__/__snapshots__/Course.mutations.test.ts.snap @@ -0,0 +1,2420 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Course mutations addCourse creates a course full: toMatchStrippedSnapshot 1`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "course_aliases": [ + { + "course_code": "alias1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_translations": [ + { + "description": "description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": null, + "name": "name_en_US", + }, + ], + "course_variants": [ + { + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "name": "new1", + "open_university_registration_links": [], + "order": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "original": StringContaining "image.gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": null, + "promote": null, + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "support_email": null, + "tags": [ + { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + }, + ], + "types": [ + "type1", + ], + }, + ], + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + }, + ], +} +`; + +exports[`Course mutations addCourse creates a course full: toMatchStrippedSnapshot 2`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email": null, + "completion_email_id": null, + "completions_handled_by": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", + "course_aliases": [ + { + "course_code": "alias1", + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_stats_email": null, + "course_stats_email_id": null, + "course_tags": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag": { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + ], + }, + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + ], + "course_translations": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "language": "en_US", + "link": null, + "name": "name_en_US", + }, + ], + "course_variants": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "exercises": [], + "handles_completions_for": [], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", + "name": "new1", + "open_university_registration_links": [], + "order": null, + "owner_organization_id": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "default": null, + "encoding": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "name": "image.gif", + "original": StringContaining "image.gif", + "original_mimetype": "image/gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": null, + "promote": null, + "services": [], + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "image": null, + "name": "module2", + "order": null, + "slug": "module2", + "study_module_translations": [ + { + "description": "module2_fi_FI", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "fi_FI", + "name": "module2_fi_FI", + "study_module_id": "00000000-0000-0000-0000-000000000101", + }, + ], + }, + ], + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, +} +`; + +exports[`Course mutations addCourse creates a course with no course tags: toMatchStrippedSnapshot 1`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "course_aliases": [ + { + "course_code": "alias1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_translations": [ + { + "description": "description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": null, + "name": "name_en_US", + }, + ], + "course_variants": [ + { + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "name": "new1", + "open_university_registration_links": [], + "order": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "original": StringContaining "image.gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": null, + "promote": null, + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "support_email": null, + "tags": [], + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + }, + ], +} +`; + +exports[`Course mutations addCourse creates a course with no course tags: toMatchStrippedSnapshot 2`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email": null, + "completion_email_id": null, + "completions_handled_by": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", + "course_aliases": [ + { + "course_code": "alias1", + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_stats_email": null, + "course_stats_email_id": null, + "course_tags": [], + "course_translations": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "language": "en_US", + "link": null, + "name": "name_en_US", + }, + ], + "course_variants": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "exercises": [], + "handles_completions_for": [], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", + "name": "new1", + "open_university_registration_links": [], + "order": null, + "owner_organization_id": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "default": null, + "encoding": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "name": "image.gif", + "original": StringContaining "image.gif", + "original_mimetype": "image/gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": null, + "promote": null, + "services": [], + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "image": null, + "name": "module2", + "order": null, + "slug": "module2", + "study_module_translations": [ + { + "description": "module2_fi_FI", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "fi_FI", + "name": "module2_fi_FI", + "study_module_id": "00000000-0000-0000-0000-000000000101", + }, + ], + }, + ], + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, +} +`; + +exports[`Course mutations addCourse creates a course with no course_translations: toMatchStrippedSnapshot 1`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "course_aliases": [ + { + "course_code": "alias1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_translations": [], + "course_variants": [ + { + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "name": "new1", + "open_university_registration_links": [], + "order": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "original": StringContaining "image.gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": null, + "promote": null, + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "support_email": null, + "tags": [ + { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + }, + ], + "types": [ + "type1", + ], + }, + ], + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + }, + ], +} +`; + +exports[`Course mutations addCourse creates a course with no course_translations: toMatchStrippedSnapshot 2`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email": null, + "completion_email_id": null, + "completions_handled_by": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", + "course_aliases": [ + { + "course_code": "alias1", + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_stats_email": null, + "course_stats_email_id": null, + "course_tags": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag": { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + ], + }, + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + ], + "course_translations": [], + "course_variants": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "exercises": [], + "handles_completions_for": [], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", + "name": "new1", + "open_university_registration_links": [], + "order": null, + "owner_organization_id": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "default": null, + "encoding": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "name": "image.gif", + "original": StringContaining "image.gif", + "original_mimetype": "image/gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": null, + "promote": null, + "services": [], + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "image": null, + "name": "module2", + "order": null, + "slug": "module2", + "study_module_translations": [ + { + "description": "module2_fi_FI", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "fi_FI", + "name": "module2_fi_FI", + "study_module_id": "00000000-0000-0000-0000-000000000101", + }, + ], + }, + ], + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, +} +`; + +exports[`Course mutations addCourse creates a course with no photo: toMatchStrippedSnapshot 1`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "course_aliases": [ + { + "course_code": "alias1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_translations": [ + { + "description": "description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": null, + "name": "name_en_US", + }, + ], + "course_variants": [ + { + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "name": "new1", + "open_university_registration_links": [], + "order": null, + "photo": null, + "points_needed": null, + "promote": null, + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "support_email": null, + "tags": [ + { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + }, + ], + "types": [ + "type1", + ], + }, + ], + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + }, + ], +} +`; + +exports[`Course mutations addCourse creates a course with no photo: toMatchStrippedSnapshot 2`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email": null, + "completion_email_id": null, + "completions_handled_by": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": "00000000-0000-0000-0000-000000001101", + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", + "course_aliases": [ + { + "course_code": "alias1", + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_stats_email": null, + "course_stats_email_id": null, + "course_tags": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag": { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + ], + }, + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + ], + "course_translations": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "language": "en_US", + "link": null, + "name": "name_en_US", + }, + ], + "course_variants": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "exercises": [], + "handles_completions_for": [], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": "00000000-0000-0000-0000-000000001101", + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", + "name": "new1", + "open_university_registration_links": [], + "order": null, + "owner_organization_id": null, + "photo": null, + "photo_id": null, + "points_needed": null, + "promote": null, + "services": [], + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "image": null, + "name": "module2", + "order": null, + "slug": "module2", + "study_module_translations": [ + { + "description": "module2_fi_FI", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "fi_FI", + "name": "module2_fi_FI", + "study_module_id": "00000000-0000-0000-0000-000000000101", + }, + ], + }, + ], + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, +} +`; + +exports[`Course mutations addCourse creates a course with no study_modules: toMatchStrippedSnapshot 1`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "course_aliases": [ + { + "course_code": "alias1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_translations": [ + { + "description": "description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": null, + "name": "name_en_US", + }, + ], + "course_variants": [ + { + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "name": "new1", + "open_university_registration_links": [], + "order": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "original": StringContaining "image.gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": null, + "promote": null, + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "support_email": null, + "tags": [ + { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + }, + ], + "types": [ + "type1", + ], + }, + ], + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + }, + ], +} +`; + +exports[`Course mutations addCourse creates a course with no study_modules: toMatchStrippedSnapshot 2`] = ` +{ + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email": null, + "completion_email_id": null, + "completions_handled_by": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", + "course_aliases": [ + { + "course_code": "alias1", + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_stats_email": null, + "course_stats_email_id": null, + "course_tags": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag": { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + ], + }, + "tag_id": "48100000-0000-0000-0000-000000000001", + }, + ], + "course_translations": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "language": "en_US", + "link": null, + "name": "name_en_US", + }, + ], + "course_variants": [ + { + "course_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": null, + "exercise_completions_needed": null, + "exercises": [], + "handles_completions_for": [], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course1", + "order": null, + "owner_organization_id": null, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + }, + "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", + "name": "new1", + "open_university_registration_links": [], + "order": null, + "owner_organization_id": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "default": null, + "encoding": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "name": "image.gif", + "original": StringContaining "image.gif", + "original_mimetype": "image/gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": null, + "promote": null, + "services": [], + "slug": "new1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher", + "tier": null, + "upcoming_active_link": false, +} +`; + +exports[`Course mutations deleteCourse deletes course on id 1`] = ` +{ + "deleteCourse": { + "id": "00000000-0000-0000-0000-000000000002", + }, +} +`; + +exports[`Course mutations deleteCourse deletes course on slug 1`] = ` +{ + "deleteCourse": { + "id": "00000000-0000-0000-0000-000000000002", + }, +} +`; + +exports[`Course mutations updateCourse deletes photo: toMatchStrippedSnapshot 1`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "course_aliases": [ + { + "course_code": "alias1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_translations": [ + { + "description": "course1_added_description_se_SE", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "se_SE", + "link": "http:/link.se.com", + "name": "course1_se_SE", + }, + { + "description": "course1_updated_description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + ], + "course_variants": [ + { + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": "12/30/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "name": "updated course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "avoin-link", + }, + ], + "order": null, + "photo": null, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "02/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "support_email": null, + "tags": [ + { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + }, + ], + "types": [ + "type1", + "type2", + ], + }, + ], + "teacher_in_charge_email": "updated-e@mail.com", + "teacher_in_charge_name": "updated teacher", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + }, + ], +} +`; + +exports[`Course mutations updateCourse deletes photo: toMatchStrippedSnapshot 2`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email": null, + "completion_email_id": null, + "completions_handled_by": { + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course2", + "order": null, + "owner_organization_id": null, + "photo_id": null, + "points_needed": null, + "promote": null, + "slug": "course2", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher2", + "tier": null, + "upcoming_active_link": false, + }, + "completions_handled_by_id": "00000000-0000-0000-0000-000000000001", + "course_aliases": [ + { + "course_code": "alias1", + "course_id": "00000000-0000-0000-0000-000000000002", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_stats_email": null, + "course_stats_email_id": null, + "course_tags": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "tag": { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + { + "name": "type2", + }, + ], + }, + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + ], + "course_translations": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "course1_added_description_se_SE", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "language": "se_SE", + "link": "http:/link.se.com", + "name": "course1_se_SE", + }, + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "course1_updated_description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": "course1_instructions_en_US", + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + ], + "course_variants": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": "12/30/2100", + "exercise_completions_needed": 1, + "exercises": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "custom_id": "customid3", + "deleted": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "max_points": 3, + "name": "exercise 3", + "part": null, + "section": null, + "service_id": "40000000-0000-0000-0000-000000000102", + "timestamp": 2021-01-01T10:00:00.000Z, + }, + { + "course_id": "00000000-0000-0000-0000-000000000002", + "custom_id": "customid4", + "deleted": true, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "max_points": null, + "name": "deleted exercise 4", + "part": null, + "section": null, + "service_id": "40000000-0000-0000-0000-000000000102", + "timestamp": 2021-01-01T10:00:00.000Z, + }, + ], + "handles_completions_for": [], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course2", + "order": null, + "owner_organization_id": null, + "photo_id": null, + "points_needed": null, + "promote": null, + "slug": "course2", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher2", + "tier": null, + "upcoming_active_link": false, + }, + "inherit_settings_from_id": "00000000-0000-0000-0000-000000000001", + "name": "updated course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "course_id": "00000000-0000-0000-0000-000000000002", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "avoin-link", + "start_date": null, + "stop_date": null, + "tiers": [ + { + "adjacent": [], + "course_id": "00000000000000000000000000000001", + "name": "intermediate tier", + "tier": 2, + }, + { + "adjacent": [ + { + "course_id": "00000000000000000000000000000001", + "name": "intermediate tier", + "tier": 2, + }, + ], + "course_id": "00000000000000000000000000000666", + "name": "advanced tier", + "tier": 3, + }, + ], + }, + ], + "order": null, + "owner_organization_id": null, + "photo": null, + "photo_id": null, + "points_needed": 3, + "promote": null, + "services": [], + "slug": "course1", + "start_date": "02/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "image": null, + "name": "module2", + "order": null, + "slug": "module2", + "study_module_translations": [ + { + "description": "module2_fi_FI", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "fi_FI", + "name": "module2_fi_FI", + "study_module_id": "00000000-0000-0000-0000-000000000101", + }, + ], + }, + ], + "support_email": null, + "teacher_in_charge_email": "updated-e@mail.com", + "teacher_in_charge_name": "updated teacher", + "tier": null, + "upcoming_active_link": false, +} +`; + +exports[`Course mutations updateCourse updates course: toMatchStrippedSnapshot 1`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "course_aliases": [ + { + "course_code": "alias1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_translations": [ + { + "description": "course1_added_description_se_SE", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "se_SE", + "link": "http:/link.se.com", + "name": "course1_se_SE", + }, + { + "description": "course1_updated_description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + ], + "course_variants": [ + { + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": "12/30/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "inherit_settings_from": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "name": "updated course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "avoin-link", + }, + ], + "order": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "original": StringContaining "original.gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": 3, + "promote": null, + "slug": "updated_course1", + "start_date": "02/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + }, + ], + "support_email": null, + "tags": [ + { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + }, + ], + "types": [ + "type1", + "type2", + ], + }, + ], + "teacher_in_charge_email": "updated-e@mail.com", + "teacher_in_charge_name": "updated teacher", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + }, + ], +} +`; + +exports[`Course mutations updateCourse updates course: toMatchStrippedSnapshot 2`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email": null, + "completion_email_id": null, + "completions_handled_by": { + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course2", + "order": null, + "owner_organization_id": null, + "photo_id": null, + "points_needed": null, + "promote": null, + "slug": "course2", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher2", + "tier": null, + "upcoming_active_link": false, + }, + "completions_handled_by_id": "00000000-0000-0000-0000-000000000001", + "course_aliases": [ + { + "course_code": "alias1", + "course_id": "00000000-0000-0000-0000-000000000002", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_stats_email": null, + "course_stats_email_id": null, + "course_tags": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "tag": { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + { + "name": "type2", + }, + ], + }, + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + ], + "course_translations": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "course1_added_description_se_SE", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "language": "se_SE", + "link": "http:/link.se.com", + "name": "course1_se_SE", + }, + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "course1_updated_description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": "course1_instructions_en_US", + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + ], + "course_variants": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": "12/30/2100", + "exercise_completions_needed": 1, + "exercises": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "custom_id": "customid3", + "deleted": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "max_points": 3, + "name": "exercise 3", + "part": null, + "section": null, + "service_id": "40000000-0000-0000-0000-000000000102", + "timestamp": 2021-01-01T10:00:00.000Z, + }, + { + "course_id": "00000000-0000-0000-0000-000000000002", + "custom_id": "customid4", + "deleted": true, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "max_points": null, + "name": "deleted exercise 4", + "part": null, + "section": null, + "service_id": "40000000-0000-0000-0000-000000000102", + "timestamp": 2021-01-01T10:00:00.000Z, + }, + ], + "handles_completions_for": [], + "has_certificate": false, + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "inherit_settings_from": { + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course2", + "order": null, + "owner_organization_id": null, + "photo_id": null, + "points_needed": null, + "promote": null, + "slug": "course2", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher2", + "tier": null, + "upcoming_active_link": false, + }, + "inherit_settings_from_id": "00000000-0000-0000-0000-000000000001", + "name": "updated course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "course_id": "00000000-0000-0000-0000-000000000002", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "avoin-link", + "start_date": null, + "stop_date": null, + "tiers": [ + { + "adjacent": [], + "course_id": "00000000000000000000000000000001", + "name": "intermediate tier", + "tier": 2, + }, + { + "adjacent": [ + { + "course_id": "00000000000000000000000000000001", + "name": "intermediate tier", + "tier": 2, + }, + ], + "course_id": "00000000000000000000000000000666", + "name": "advanced tier", + "tier": 3, + }, + ], + }, + ], + "order": null, + "owner_organization_id": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "default": null, + "encoding": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "name": null, + "original": StringContaining "original.gif", + "original_mimetype": "image/gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "photo_id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "points_needed": 3, + "promote": null, + "services": [], + "slug": "updated_course1", + "start_date": "02/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + "image": null, + "name": "module2", + "order": null, + "slug": "module2", + "study_module_translations": [ + { + "description": "module2_fi_FI", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "fi_FI", + "name": "module2_fi_FI", + "study_module_id": "00000000-0000-0000-0000-000000000101", + }, + ], + }, + ], + "support_email": null, + "teacher_in_charge_email": "updated-e@mail.com", + "teacher_in_charge_name": "updated teacher", + "tier": null, + "upcoming_active_link": false, +} +`; + +exports[`Course mutations updateCourse updates photo: toMatchStrippedSnapshot 1`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "course_aliases": [ + { + "course_code": "alias1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_translations": [ + { + "description": "course1_added_description_se_SE", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "se_SE", + "link": "http:/link.se.com", + "name": "course1_se_SE", + }, + { + "description": "course1_updated_description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + ], + "course_variants": [ + { + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": "12/30/2100", + "exercise_completions_needed": 1, + "has_certificate": false, + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "inherit_settings_from": { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + "name": "updated course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "avoin-link", + }, + ], + "order": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "original": StringContaining "image.gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": 3, + "promote": null, + "slug": "updated_course1", + "start_date": "02/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + }, + ], + "support_email": null, + "tags": [ + { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + }, + ], + "types": [ + "type1", + "type2", + ], + }, + ], + "teacher_in_charge_email": "updated-e@mail.com", + "teacher_in_charge_name": "updated teacher", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + }, + ], +} +`; + +exports[`Course mutations updateCourse updates photo: toMatchStrippedSnapshot 2`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completion_email": null, + "completion_email_id": null, + "completions_handled_by": { + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course2", + "order": null, + "owner_organization_id": null, + "photo_id": null, + "points_needed": null, + "promote": null, + "slug": "course2", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher2", + "tier": null, + "upcoming_active_link": false, + }, + "completions_handled_by_id": "00000000-0000-0000-0000-000000000001", + "course_aliases": [ + { + "course_code": "alias1", + "course_id": "00000000-0000-0000-0000-000000000002", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + }, + ], + "course_stats_email": null, + "course_stats_email_id": null, + "course_tags": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "tag": { + "hidden": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + { + "name": "type2", + }, + ], + }, + "tag_id": "48100000-0000-0000-0000-000000000002", + }, + ], + "course_translations": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "course1_added_description_se_SE", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "language": "se_SE", + "link": "http:/link.se.com", + "name": "course1_se_SE", + }, + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "course1_updated_description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": "course1_instructions_en_US", + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + ], + "course_variants": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "description": "variant1", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "instructions": null, + "slug": "variant1", + }, + ], + "ects": null, + "end_date": "12/30/2100", + "exercise_completions_needed": 1, + "exercises": [ + { + "course_id": "00000000-0000-0000-0000-000000000002", + "custom_id": "customid3", + "deleted": false, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "max_points": 3, + "name": "exercise 3", + "part": null, + "section": null, + "service_id": "40000000-0000-0000-0000-000000000102", + "timestamp": 2021-01-01T10:00:00.000Z, + }, + { + "course_id": "00000000-0000-0000-0000-000000000002", + "custom_id": "customid4", + "deleted": true, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "max_points": null, + "name": "deleted exercise 4", + "part": null, + "section": null, + "service_id": "40000000-0000-0000-0000-000000000102", + "timestamp": 2021-01-01T10:00:00.000Z, + }, + ], + "handles_completions_for": [], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": { + "automatic_completions": false, + "automatic_completions_eligible_for_ects": true, + "completion_email_id": null, + "completions_handled_by_id": null, + "course_stats_email_id": null, + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": null, + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from_id": null, + "name": "course2", + "order": null, + "owner_organization_id": null, + "photo_id": null, + "points_needed": null, + "promote": null, + "slug": "course2", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "support_email": null, + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher2", + "tier": null, + "upcoming_active_link": false, + }, + "inherit_settings_from_id": "00000000-0000-0000-0000-000000000001", + "name": "updated course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "course_id": "00000000-0000-0000-0000-000000000002", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "en_US", + "link": "avoin-link", + "start_date": null, + "stop_date": null, + "tiers": [ + { + "adjacent": [], + "course_id": "00000000000000000000000000000001", + "name": "intermediate tier", + "tier": 2, + }, + { + "adjacent": [ + { + "course_id": "00000000000000000000000000000001", + "name": "intermediate tier", + "tier": 2, + }, + ], + "course_id": "00000000000000000000000000000666", + "name": "advanced tier", + "tier": 3, + }, + ], + }, + ], + "order": null, + "owner_organization_id": null, + "photo": { + "compressed": StringContaining "webp", + "compressed_mimetype": "image/webp", + "default": null, + "encoding": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "name": "image.gif", + "original": StringContaining "image.gif", + "original_mimetype": "image/gif", + "uncompressed": StringContaining "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "photo_id": StringNotContaining "00000000000000000000000000001101", + "points_needed": 3, + "promote": null, + "services": [], + "slug": "updated_course1", + "start_date": "02/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "image": null, + "name": "module2", + "order": null, + "slug": "module2", + "study_module_translations": [ + { + "description": "module2_fi_FI", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "language": "fi_FI", + "name": "module2_fi_FI", + "study_module_id": "00000000-0000-0000-0000-000000000101", + }, + ], + }, + ], + "support_email": null, + "teacher_in_charge_email": "updated-e@mail.com", + "teacher_in_charge_name": "updated teacher", + "tier": null, + "upcoming_active_link": false, +} +`; diff --git a/backend/graphql/Course/__test__/__snapshots__/Course.queries.test.ts.snap b/backend/graphql/Course/__test__/__snapshots__/Course.queries.test.ts.snap new file mode 100644 index 000000000..32e64c7c4 --- /dev/null +++ b/backend/graphql/Course/__test__/__snapshots__/Course.queries.test.ts.snap @@ -0,0 +1,1160 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Course queries course admin returns full course on id and slug 1`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": null, + "course_aliases": [ + { + "course_code": "alias", + "id": "67000000-0000-0000-0000-000000000001", + }, + ], + "course_translations": [ + { + "description": "course1_description_en_US", + "id": "00000000-0000-0000-0000-000000000011", + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + { + "description": "course1_description_fi_FI", + "id": "00000000-0000-0000-0000-000000000012", + "language": "fi_FI", + "link": "http:/link.fi.com", + "name": "course1_fi_FI", + }, + ], + "course_variants": [], + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "exercises": [ + { + "deleted": false, + "id": "50000000-0000-0000-0000-000000000003", + "name": "exercise 3", + }, + ], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": null, + "name": "course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", + "language": "en_US", + "link": "avoin-link", + }, + ], + "order": null, + "photo": { + "compressed": "webp", + "compressed_mimetype": "image/webp", + "id": "00000000-0000-0000-0000-000000001101", + "uncompressed": "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + }, + { + "id": "00000000-0000-0000-0000-000000000102", + }, + ], + "support_email": null, + "tags": [ + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000001", + "name": null, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + ], + "types": [ + "type1", + ], + }, + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000002", + "name": null, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + { + "name": "type2", + }, + ], + "types": [ + "type1", + "type2", + ], + }, + ], + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [], +} +`; + +exports[`Course queries course admin returns full course on id and slug 2`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": null, + "course_aliases": [ + { + "course_code": "alias", + "id": "67000000-0000-0000-0000-000000000001", + }, + ], + "course_translations": [ + { + "description": "course1_description_en_US", + "id": "00000000-0000-0000-0000-000000000011", + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + { + "description": "course1_description_fi_FI", + "id": "00000000-0000-0000-0000-000000000012", + "language": "fi_FI", + "link": "http:/link.fi.com", + "name": "course1_fi_FI", + }, + ], + "course_variants": [], + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "exercises": [ + { + "deleted": false, + "id": "50000000-0000-0000-0000-000000000003", + "name": "exercise 3", + }, + ], + "has_certificate": false, + "hidden": null, + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "inherit_settings_from": null, + "name": "course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", + "language": "en_US", + "link": "avoin-link", + }, + ], + "order": null, + "photo": { + "compressed": "webp", + "compressed_mimetype": "image/webp", + "id": "00000000-0000-0000-0000-000000001101", + "uncompressed": "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + }, + { + "id": "00000000-0000-0000-0000-000000000102", + }, + ], + "support_email": null, + "tags": [ + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000001", + "name": null, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + ], + "types": [ + "type1", + ], + }, + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000002", + "name": null, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + { + "name": "type2", + }, + ], + "types": [ + "type1", + "type2", + ], + }, + ], + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [], +} +`; + +exports[`Course queries course admin should include deleted exercises if specified 1`] = ` +{ + "automatic_completions": true, + "automatic_completions_eligible_for_ects": true, + "completions_handled_by": null, + "course_aliases": [ + { + "course_code": "alias", + "id": "67000000-0000-0000-0000-000000000001", + }, + ], + "course_translations": [ + { + "description": "course1_description_en_US", + "id": "00000000-0000-0000-0000-000000000011", + "language": "en_US", + "link": "http://link.com", + "name": "course1_en_US", + }, + { + "description": "course1_description_fi_FI", + "id": "00000000-0000-0000-0000-000000000012", + "language": "fi_FI", + "link": "http:/link.fi.com", + "name": "course1_fi_FI", + }, + ], + "course_variants": [], + "ects": null, + "end_date": "12/31/2100", + "exercise_completions_needed": 1, + "exercises": [ + { + "deleted": false, + "id": "50000000-0000-0000-0000-000000000003", + "name": "exercise 3", + }, + { + "deleted": true, + "id": "50000000-0000-0000-0000-000000000004", + "name": "deleted exercise 4", + }, + ], + "has_certificate": false, + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "inherit_settings_from": null, + "name": "course1", + "open_university_registration_links": [ + { + "course_code": "alias", + "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", + "language": "en_US", + "link": "avoin-link", + }, + ], + "order": null, + "photo": { + "compressed": "webp", + "compressed_mimetype": "image/webp", + "id": "00000000-0000-0000-0000-000000001101", + "uncompressed": "jpeg", + "uncompressed_mimetype": "image/jpeg", + }, + "points_needed": 3, + "promote": null, + "slug": "course1", + "start_date": "01/01/1900", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + }, + { + "id": "00000000-0000-0000-0000-000000000102", + }, + ], + "support_email": null, + "tags": [ + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000001", + "name": null, + "tag_translations": [ + { + "description": "tag1 description", + "language": "en_US", + "name": "tag1 in english", + }, + { + "description": "tag1 kuvaus", + "language": "fi_FI", + "name": "tag1 suomeksi", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + ], + "types": [ + "type1", + ], + }, + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000002", + "name": null, + "tag_translations": [ + { + "description": "tag2 description", + "language": "en_US", + "name": "tag2 in english", + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "language": "fi_FI", + "name": "tag2 suomeksi", + }, + ], + "tag_types": [ + { + "name": "type1", + }, + { + "name": "type2", + }, + ], + "types": [ + "type1", + "type2", + ], + }, + ], + "teacher_in_charge_email": "e@mail.com", + "teacher_in_charge_name": "teacher1", + "tier": null, + "upcoming_active_link": false, + "user_course_settings_visibilities": [], +} +`; + +exports[`Course queries course normal user returns correct language 1`] = ` +{ + "description": "course1_description_en_US", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "link": "http://link.com", + "name": "course1_en_US", + "slug": "course1", +} +`; + +exports[`Course queries course normal user returns course on id and slug 1`] = ` +{ + "description": "", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "link": "", + "name": "course1", + "slug": "course1", +} +`; + +exports[`Course queries course normal user returns course on id and slug 2`] = ` +{ + "description": "", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "link": "", + "name": "course1", + "slug": "course1", +} +`; + +exports[`Course queries courses filters handledBy: courses-hidden-foo 1`] = `[]`; + +exports[`Course queries courses filters handledBy: courses-hidden-handler 1`] = ` +[ + "00000000-0000-0000-0000-000000000667", +] +`; + +exports[`Course queries courses filters hidden: courses-hidden-false 1`] = ` +[ + "00000000-0000-0000-0000-000000000001", + "00000000-0000-0000-0000-000000000002", + "00000000-0000-0000-0000-000000000666", +] +`; + +exports[`Course queries courses filters hidden: courses-hidden-null 1`] = ` +[ + "00000000-0000-0000-0000-000000000001", + "00000000-0000-0000-0000-000000000002", + "00000000-0000-0000-0000-000000000666", +] +`; + +exports[`Course queries courses filters hidden: courses-hidden-true 1`] = ` +[ + "00000000-0000-0000-0000-000000000001", + "00000000-0000-0000-0000-000000000002", + "00000000-0000-0000-0000-000000000666", + "00000000-0000-0000-0000-000000000667", + "00000000-0000-0000-0000-000000000668", +] +`; + +exports[`Course queries courses returns courses 1`] = ` +[ + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000022", + "language": "fi_FI", + "name": "course2_fi_FI", + }, + ], + "description": "", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000001", + "link": "", + "name": "course2", + "order": null, + "photo": null, + "promote": null, + "slug": "course2", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000011", + "language": "en_US", + "name": "course1_en_US", + }, + { + "id": "00000000-0000-0000-0000-000000000012", + "language": "fi_FI", + "name": "course1_fi_FI", + }, + ], + "description": "", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "link": "", + "name": "course1", + "order": null, + "photo": { + "compressed": "webp", + "id": "00000000-0000-0000-0000-000000001101", + "uncompressed": "jpeg", + }, + "promote": null, + "slug": "course1", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + "slug": "module2", + }, + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [ + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000001", + "name": null, + "types": [ + "type1", + ], + }, + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000002", + "name": null, + "types": [ + "type1", + "type2", + ], + }, + ], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [], + "description": "", + "hidden": false, + "id": "00000000-0000-0000-0000-000000000666", + "link": "", + "name": "handler", + "order": null, + "photo": null, + "promote": null, + "slug": "handler", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [], + "description": "", + "hidden": true, + "id": "00000000-0000-0000-0000-000000000667", + "link": "", + "name": "handled", + "order": null, + "photo": null, + "promote": null, + "slug": "handled", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [], + "description": "", + "hidden": true, + "id": "00000000-0000-0000-0000-000000000668", + "link": "", + "name": "inherits", + "order": null, + "photo": null, + "promote": null, + "slug": "inherits", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, +] +`; + +exports[`Course queries courses returns courses filtered by language: courses-language-bogus 1`] = `[]`; + +exports[`Course queries courses returns courses filtered by language: courses-language-en_US 1`] = ` +[ + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000011", + "language": "en_US", + "name": "course1_en_US", + }, + { + "id": "00000000-0000-0000-0000-000000000012", + "language": "fi_FI", + "name": "course1_fi_FI", + }, + ], + "description": "course1_description_en_US", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "link": "http://link.com", + "name": "course1", + "order": null, + "photo": { + "compressed": "webp", + "id": "00000000-0000-0000-0000-000000001101", + "uncompressed": "jpeg", + }, + "promote": null, + "slug": "course1", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + "slug": "module2", + }, + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [ + { + "description": "tag1 description", + "hidden": false, + "id": "48100000-0000-0000-0000-000000000001", + "name": "tag1 in english", + "types": [ + "type1", + ], + }, + { + "description": "tag2 description", + "hidden": false, + "id": "48100000-0000-0000-0000-000000000002", + "name": "tag2 in english", + "types": [ + "type1", + "type2", + ], + }, + ], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, +] +`; + +exports[`Course queries courses returns courses filtered by language: courses-language-fi_FI 1`] = ` +[ + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000022", + "language": "fi_FI", + "name": "course2_fi_FI", + }, + ], + "description": "course2_description_fi_FI", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000001", + "link": "", + "name": "course2", + "order": null, + "photo": null, + "promote": null, + "slug": "course2", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000011", + "language": "en_US", + "name": "course1_en_US", + }, + { + "id": "00000000-0000-0000-0000-000000000012", + "language": "fi_FI", + "name": "course1_fi_FI", + }, + ], + "description": "course1_description_fi_FI", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "link": "http:/link.fi.com", + "name": "course1", + "order": null, + "photo": { + "compressed": "webp", + "id": "00000000-0000-0000-0000-000000001101", + "uncompressed": "jpeg", + }, + "promote": null, + "slug": "course1", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + "slug": "module2", + }, + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [ + { + "description": "tag1 kuvaus", + "hidden": false, + "id": "48100000-0000-0000-0000-000000000001", + "name": "tag1 suomeksi", + "types": [ + "type1", + ], + }, + { + "description": "tag2 kuvaus ja jotain muuta", + "hidden": false, + "id": "48100000-0000-0000-0000-000000000002", + "name": "tag2 suomeksi", + "types": [ + "type1", + "type2", + ], + }, + ], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, +] +`; + +exports[`Course queries courses returns courses ordered: courses-order-asc 1`] = ` +[ + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000011", + "language": "en_US", + "name": "course1_en_US", + }, + { + "id": "00000000-0000-0000-0000-000000000012", + "language": "fi_FI", + "name": "course1_fi_FI", + }, + ], + "description": "", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "link": "", + "name": "course1", + "order": null, + "photo": { + "compressed": "webp", + "id": "00000000-0000-0000-0000-000000001101", + "uncompressed": "jpeg", + }, + "promote": null, + "slug": "course1", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + "slug": "module2", + }, + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [ + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000001", + "name": null, + "types": [ + "type1", + ], + }, + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000002", + "name": null, + "types": [ + "type1", + "type2", + ], + }, + ], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000022", + "language": "fi_FI", + "name": "course2_fi_FI", + }, + ], + "description": "", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000001", + "link": "", + "name": "course2", + "order": null, + "photo": null, + "promote": null, + "slug": "course2", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [], + "description": "", + "hidden": true, + "id": "00000000-0000-0000-0000-000000000667", + "link": "", + "name": "handled", + "order": null, + "photo": null, + "promote": null, + "slug": "handled", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [], + "description": "", + "hidden": false, + "id": "00000000-0000-0000-0000-000000000666", + "link": "", + "name": "handler", + "order": null, + "photo": null, + "promote": null, + "slug": "handler", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [], + "description": "", + "hidden": true, + "id": "00000000-0000-0000-0000-000000000668", + "link": "", + "name": "inherits", + "order": null, + "photo": null, + "promote": null, + "slug": "inherits", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, +] +`; + +exports[`Course queries courses returns courses ordered: courses-order-desc 1`] = ` +[ + { + "course_translations": [], + "description": "", + "hidden": true, + "id": "00000000-0000-0000-0000-000000000668", + "link": "", + "name": "inherits", + "order": null, + "photo": null, + "promote": null, + "slug": "inherits", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [], + "description": "", + "hidden": false, + "id": "00000000-0000-0000-0000-000000000666", + "link": "", + "name": "handler", + "order": null, + "photo": null, + "promote": null, + "slug": "handler", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [], + "description": "", + "hidden": true, + "id": "00000000-0000-0000-0000-000000000667", + "link": "", + "name": "handled", + "order": null, + "photo": null, + "promote": null, + "slug": "handled", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000022", + "language": "fi_FI", + "name": "course2_fi_FI", + }, + ], + "description": "", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000001", + "link": "", + "name": "course2", + "order": null, + "photo": null, + "promote": null, + "slug": "course2", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, + { + "course_translations": [ + { + "id": "00000000-0000-0000-0000-000000000011", + "language": "en_US", + "name": "course1_en_US", + }, + { + "id": "00000000-0000-0000-0000-000000000012", + "language": "fi_FI", + "name": "course1_fi_FI", + }, + ], + "description": "", + "hidden": null, + "id": "00000000-0000-0000-0000-000000000002", + "link": "", + "name": "course1", + "order": null, + "photo": { + "compressed": "webp", + "id": "00000000-0000-0000-0000-000000001101", + "uncompressed": "jpeg", + }, + "promote": null, + "slug": "course1", + "start_point": null, + "status": "Upcoming", + "study_module_order": null, + "study_module_start_point": null, + "study_modules": [ + { + "id": "00000000-0000-0000-0000-000000000101", + "slug": "module2", + }, + { + "id": "00000000-0000-0000-0000-000000000102", + "slug": "module1", + }, + ], + "tags": [ + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000001", + "name": null, + "types": [ + "type1", + ], + }, + { + "description": null, + "hidden": false, + "id": "48100000-0000-0000-0000-000000000002", + "name": null, + "types": [ + "type1", + "type2", + ], + }, + ], + "upcoming_active_link": false, + "user_course_settings_visibilities": [], + }, +] +`; + +exports[`Course queries handlerCourses returns correctly 1`] = ` +[ + { + "handles_completions_for": [ + { + "id": "00000000-0000-0000-0000-000000000667", + }, + ], + "id": "00000000-0000-0000-0000-000000000666", + }, +] +`; diff --git a/backend/graphql/Course/__test__/__snapshots__/Course.test.ts.snap b/backend/graphql/Course/__test__/__snapshots__/Course.test.ts.snap index 03745f15d..c3e4aa820 100644 --- a/backend/graphql/Course/__test__/__snapshots__/Course.test.ts.snap +++ b/backend/graphql/Course/__test__/__snapshots__/Course.test.ts.snap @@ -1,25 +1,25 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Course model completions shouldn't return anything with non-existent user 1`] = ` -Object { - "completions": Array [], - "course": Object { - "completions": Array [], +{ + "completions": [], + "course": { + "completions": [], "id": "00000000-0000-0000-0000-000000000002", }, } `; exports[`Course model completions works with user_id 1`] = ` -Object { - "completions": Array [], - "course": Object { - "completions": Array [ - Object { +{ + "completions": [], + "course": { + "completions": [ + { "completion_language": null, "email": "what@ever.com", "id": "12400000-0000-0000-0000-000000000001", - "user": Object { + "user": { "id": "20000000-0000-0000-0000-000000000103", "username": "admin", }, @@ -32,15 +32,15 @@ Object { `; exports[`Course model completions works with user_upstream_id 1`] = ` -Object { - "completions": Array [], - "course": Object { - "completions": Array [ - Object { +{ + "completions": [], + "course": { + "completions": [ + { "completion_language": null, "email": "e@mail.com", "id": "30000000-0000-0000-0000-000000000102", - "user": Object { + "user": { "id": "20000000-0000-0000-0000-000000000102", "username": "existing_user", }, @@ -51,1700 +51,3 @@ Object { }, } `; - -exports[`Course mutations addCourse creates a course full 1`] = ` -Object { - "addCourse": Object { - "automatic_completions": false, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, - "course_aliases": Array [ - Object { - "course_code": "alias1", - "id": Any, - }, - ], - "course_translations": Array [ - Object { - "description": "description_en_US", - "id": Any, - "language": "en_US", - "link": null, - "name": "name_en_US", - }, - ], - "course_variants": Array [ - Object { - "description": "variant1", - "id": Any, - "slug": "variant1", - }, - ], - "ects": null, - "end_date": null, - "exercise_completions_needed": null, - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, - "name": "new1", - "open_university_registration_links": Array [], - "order": null, - "photo": Object { - "compressed": StringContaining "webp", - "compressed_mimetype": "image/webp", - "id": Any, - "original": StringContaining "image.gif", - "uncompressed": StringContaining "jpeg", - "uncompressed_mimetype": "image/jpeg", - }, - "points_needed": null, - "promote": null, - "slug": "new1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - }, - ], - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [ - Object { - "id": Any, - "language": "en_US", - }, - ], - }, -} -`; - -exports[`Course mutations addCourse creates a course full 2`] = ` -Object { - "automatic_completions": false, - "automatic_completions_eligible_for_ects": true, - "completion_email_id": null, - "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", - "course_stats_email_id": null, - "created_at": Any, - "ects": null, - "end_date": null, - "exercise_completions_needed": null, - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", - "name": "new1", - "order": null, - "owner_organization_id": null, - "photo_id": Any, - "points_needed": null, - "promote": null, - "slug": "new1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher", - "tier": null, - "upcoming_active_link": false, - "updated_at": Any, -} -`; - -exports[`Course mutations addCourse creates a course with no course_translations 1`] = ` -Object { - "addCourse": Object { - "automatic_completions": false, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, - "course_aliases": Array [ - Object { - "course_code": "alias1", - "id": Any, - }, - ], - "course_translations": Array [], - "course_variants": Array [ - Object { - "description": "variant1", - "id": Any, - "slug": "variant1", - }, - ], - "ects": null, - "end_date": null, - "exercise_completions_needed": null, - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, - "name": "new1", - "open_university_registration_links": Array [], - "order": null, - "photo": Object { - "compressed": StringContaining "webp", - "compressed_mimetype": "image/webp", - "id": Any, - "original": StringContaining "image.gif", - "uncompressed": StringContaining "jpeg", - "uncompressed_mimetype": "image/jpeg", - }, - "points_needed": null, - "promote": null, - "slug": "new1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - }, - ], - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [ - Object { - "id": Any, - "language": "en_US", - }, - ], - }, -} -`; - -exports[`Course mutations addCourse creates a course with no course_translations 2`] = ` -Object { - "automatic_completions": false, - "automatic_completions_eligible_for_ects": true, - "completion_email_id": null, - "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", - "course_stats_email_id": null, - "created_at": Any, - "ects": null, - "end_date": null, - "exercise_completions_needed": null, - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", - "name": "new1", - "order": null, - "owner_organization_id": null, - "photo_id": Any, - "points_needed": null, - "promote": null, - "slug": "new1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher", - "tier": null, - "upcoming_active_link": false, - "updated_at": Any, -} -`; - -exports[`Course mutations addCourse creates a course with no photo 1`] = ` -Object { - "addCourse": Object { - "automatic_completions": false, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, - "course_aliases": Array [ - Object { - "course_code": "alias1", - "id": Any, - }, - ], - "course_translations": Array [ - Object { - "description": "description_en_US", - "id": Any, - "language": "en_US", - "link": null, - "name": "name_en_US", - }, - ], - "course_variants": Array [ - Object { - "description": "variant1", - "id": Any, - "slug": "variant1", - }, - ], - "ects": null, - "end_date": null, - "exercise_completions_needed": null, - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, - "name": "new1", - "open_university_registration_links": Array [], - "order": null, - "photo": null, - "points_needed": null, - "promote": null, - "slug": "new1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - }, - ], - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [ - Object { - "id": Any, - "language": "en_US", - }, - ], - }, -} -`; - -exports[`Course mutations addCourse creates a course with no photo 2`] = ` -Object { - "automatic_completions": false, - "automatic_completions_eligible_for_ects": true, - "completion_email_id": null, - "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", - "course_stats_email_id": null, - "created_at": Any, - "ects": null, - "end_date": null, - "exercise_completions_needed": null, - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", - "name": "new1", - "order": null, - "owner_organization_id": null, - "photo_id": null, - "points_needed": null, - "promote": null, - "slug": "new1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher", - "tier": null, - "upcoming_active_link": false, - "updated_at": Any, -} -`; - -exports[`Course mutations addCourse creates a course with no study_modules 1`] = ` -Object { - "addCourse": Object { - "automatic_completions": false, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, - "course_aliases": Array [ - Object { - "course_code": "alias1", - "id": Any, - }, - ], - "course_translations": Array [ - Object { - "description": "description_en_US", - "id": Any, - "language": "en_US", - "link": null, - "name": "name_en_US", - }, - ], - "course_variants": Array [ - Object { - "description": "variant1", - "id": Any, - "slug": "variant1", - }, - ], - "ects": null, - "end_date": null, - "exercise_completions_needed": null, - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, - "name": "new1", - "open_university_registration_links": Array [], - "order": null, - "photo": Object { - "compressed": StringContaining "webp", - "compressed_mimetype": "image/webp", - "id": Any, - "original": StringContaining "image.gif", - "uncompressed": StringContaining "jpeg", - "uncompressed_mimetype": "image/jpeg", - }, - "points_needed": null, - "promote": null, - "slug": "new1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [ - Object { - "id": Any, - "language": "en_US", - }, - ], - }, -} -`; - -exports[`Course mutations addCourse creates a course with no study_modules 2`] = ` -Object { - "automatic_completions": false, - "automatic_completions_eligible_for_ects": true, - "completion_email_id": null, - "completions_handled_by_id": "00000000-0000-0000-0000-000000000002", - "course_stats_email_id": null, - "created_at": Any, - "ects": null, - "end_date": null, - "exercise_completions_needed": null, - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from_id": "00000000-0000-0000-0000-000000000002", - "name": "new1", - "order": null, - "owner_organization_id": null, - "photo_id": Any, - "points_needed": null, - "promote": null, - "slug": "new1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher", - "tier": null, - "upcoming_active_link": false, - "updated_at": Any, -} -`; - -exports[`Course mutations deleteCourse deletes course on id 1`] = ` -Object { - "deleteCourse": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, -} -`; - -exports[`Course mutations deleteCourse deletes course on slug 1`] = ` -Object { - "deleteCourse": Object { - "id": "00000000-0000-0000-0000-000000000002", - }, -} -`; - -exports[`Course mutations updateCourse deletes photo 1`] = ` -Object { - "updateCourse": Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": Object { - "id": "00000000-0000-0000-0000-000000000001", - }, - "course_aliases": Array [ - Object { - "course_code": "alias1", - "id": Any, - }, - ], - "course_translations": Array [ - Object { - "description": "course1_added_description_se_SE", - "id": Any, - "language": "se_SE", - "link": "http:/link.se.com", - "name": "course1_se_SE", - }, - Object { - "description": "course1_updated_description_en_US", - "id": Any, - "language": "en_US", - "link": "http://link.com", - "name": "course1_en_US", - }, - ], - "course_variants": Array [ - Object { - "description": "variant1", - "id": Any, - "slug": "variant1", - }, - ], - "ects": null, - "end_date": "12/30/2100", - "exercise_completions_needed": 1, - "has_certificate": false, - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "inherit_settings_from": Object { - "id": "00000000-0000-0000-0000-000000000001", - }, - "name": "updated course1", - "open_university_registration_links": Array [ - Object { - "course_code": "alias", - "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", - "language": "en_US", - "link": "avoin-link", - }, - ], - "order": null, - "photo": null, - "points_needed": 3, - "promote": null, - "slug": "course1", - "start_date": "02/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": StringMatching /00000000-0000-0000-0000-000000000101/, - }, - ], - "support_email": null, - "teacher_in_charge_email": "updated-e@mail.com", - "teacher_in_charge_name": "updated teacher", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [ - Object { - "id": Any, - "language": "en_US", - }, - ], - }, -} -`; - -exports[`Course mutations updateCourse deletes photo 2`] = ` -Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completion_email_id": null, - "completions_handled_by_id": "00000000-0000-0000-0000-000000000001", - "course_stats_email_id": null, - "created_at": Any, - "ects": null, - "end_date": "12/30/2100", - "exercise_completions_needed": 1, - "has_certificate": false, - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "inherit_settings_from_id": "00000000-0000-0000-0000-000000000001", - "name": "updated course1", - "order": null, - "owner_organization_id": null, - "photo_id": null, - "points_needed": 3, - "promote": null, - "slug": "course1", - "start_date": "02/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "support_email": null, - "teacher_in_charge_email": "updated-e@mail.com", - "teacher_in_charge_name": "updated teacher", - "tier": null, - "upcoming_active_link": false, - "updated_at": Any, -} -`; - -exports[`Course mutations updateCourse updates course 1`] = ` -Object { - "updateCourse": Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": Object { - "id": "00000000-0000-0000-0000-000000000001", - }, - "course_aliases": Array [ - Object { - "course_code": "alias1", - "id": Any, - }, - ], - "course_translations": Array [ - Object { - "description": "course1_added_description_se_SE", - "id": Any, - "language": "se_SE", - "link": "http:/link.se.com", - "name": "course1_se_SE", - }, - Object { - "description": "course1_updated_description_en_US", - "id": Any, - "language": "en_US", - "link": "http://link.com", - "name": "course1_en_US", - }, - ], - "course_variants": Array [ - Object { - "description": "variant1", - "id": Any, - "slug": "variant1", - }, - ], - "ects": null, - "end_date": "12/30/2100", - "exercise_completions_needed": 1, - "has_certificate": false, - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "inherit_settings_from": Object { - "id": "00000000-0000-0000-0000-000000000001", - }, - "name": "updated course1", - "open_university_registration_links": Array [ - Object { - "course_code": "alias", - "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", - "language": "en_US", - "link": "avoin-link", - }, - ], - "order": null, - "photo": Object { - "compressed": StringContaining "webp", - "compressed_mimetype": "image/webp", - "id": Any, - "original": StringContaining "original.gif", - "uncompressed": StringContaining "jpeg", - "uncompressed_mimetype": "image/jpeg", - }, - "points_needed": 3, - "promote": null, - "slug": "updated_course1", - "start_date": "02/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": StringMatching /00000000-0000-0000-0000-000000000101/, - }, - ], - "support_email": null, - "teacher_in_charge_email": "updated-e@mail.com", - "teacher_in_charge_name": "updated teacher", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [ - Object { - "id": Any, - "language": "en_US", - }, - ], - }, -} -`; - -exports[`Course mutations updateCourse updates course 2`] = ` -Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completion_email_id": null, - "completions_handled_by_id": "00000000-0000-0000-0000-000000000001", - "course_stats_email_id": null, - "created_at": Any, - "ects": null, - "end_date": "12/30/2100", - "exercise_completions_needed": 1, - "has_certificate": false, - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "inherit_settings_from_id": "00000000-0000-0000-0000-000000000001", - "name": "updated course1", - "order": null, - "owner_organization_id": null, - "photo_id": Any, - "points_needed": 3, - "promote": null, - "slug": "updated_course1", - "start_date": "02/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "support_email": null, - "teacher_in_charge_email": "updated-e@mail.com", - "teacher_in_charge_name": "updated teacher", - "tier": null, - "upcoming_active_link": false, - "updated_at": Any, -} -`; - -exports[`Course mutations updateCourse updates photo 1`] = ` -Object { - "updateCourse": Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": Object { - "id": "00000000-0000-0000-0000-000000000001", - }, - "course_aliases": Array [ - Object { - "course_code": "alias1", - "id": Any, - }, - ], - "course_translations": Array [ - Object { - "description": "course1_added_description_se_SE", - "id": Any, - "language": "se_SE", - "link": "http:/link.se.com", - "name": "course1_se_SE", - }, - Object { - "description": "course1_updated_description_en_US", - "id": Any, - "language": "en_US", - "link": "http://link.com", - "name": "course1_en_US", - }, - ], - "course_variants": Array [ - Object { - "description": "variant1", - "id": Any, - "slug": "variant1", - }, - ], - "ects": null, - "end_date": "12/30/2100", - "exercise_completions_needed": 1, - "has_certificate": false, - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "inherit_settings_from": Object { - "id": "00000000-0000-0000-0000-000000000001", - }, - "name": "updated course1", - "open_university_registration_links": Array [ - Object { - "course_code": "alias", - "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", - "language": "en_US", - "link": "avoin-link", - }, - ], - "order": null, - "photo": Object { - "compressed": StringContaining "webp", - "compressed_mimetype": "image/webp", - "id": Any, - "original": StringContaining "image.gif", - "uncompressed": StringContaining "jpeg", - "uncompressed_mimetype": "image/jpeg", - }, - "points_needed": 3, - "promote": null, - "slug": "updated_course1", - "start_date": "02/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": StringMatching /00000000-0000-0000-0000-000000000101/, - }, - ], - "support_email": null, - "teacher_in_charge_email": "updated-e@mail.com", - "teacher_in_charge_name": "updated teacher", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [ - Object { - "id": Any, - "language": "en_US", - }, - ], - }, -} -`; - -exports[`Course mutations updateCourse updates photo 2`] = ` -Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completion_email_id": null, - "completions_handled_by_id": "00000000-0000-0000-0000-000000000001", - "course_stats_email_id": null, - "created_at": Any, - "ects": null, - "end_date": "12/30/2100", - "exercise_completions_needed": 1, - "has_certificate": false, - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "inherit_settings_from_id": "00000000-0000-0000-0000-000000000001", - "name": "updated course1", - "order": null, - "owner_organization_id": null, - "photo_id": Any, - "points_needed": 3, - "promote": null, - "slug": "updated_course1", - "start_date": "02/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "support_email": null, - "teacher_in_charge_email": "updated-e@mail.com", - "teacher_in_charge_name": "updated teacher", - "tier": null, - "upcoming_active_link": false, - "updated_at": Any, -} -`; - -exports[`Course queries course admin returns full course on id and slug 1`] = ` -Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": null, - "course_aliases": Array [ - Object { - "course_code": "alias", - "id": "67000000-0000-0000-0000-000000000001", - }, - ], - "course_translations": Array [ - Object { - "description": "course1_description_en_US", - "id": "00000000-0000-0000-0000-000000000011", - "language": "en_US", - "link": "http://link.com", - "name": "course1_en_US", - }, - Object { - "description": "course1_description_fi_FI", - "id": "00000000-0000-0000-0000-000000000012", - "language": "fi_FI", - "link": "http:/link.fi.com", - "name": "course1_fi_FI", - }, - ], - "course_variants": Array [], - "ects": null, - "end_date": "12/31/2100", - "exercise_completions_needed": 1, - "exercises": Array [ - Object { - "deleted": false, - "id": "50000000-0000-0000-0000-000000000003", - "name": "exercise 3", - }, - ], - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from": null, - "name": "course1", - "open_university_registration_links": Array [ - Object { - "course_code": "alias", - "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", - "language": "en_US", - "link": "avoin-link", - }, - ], - "order": null, - "photo": Object { - "compressed": "webp", - "compressed_mimetype": "image/webp", - "id": "00000000-0000-0000-0000-000000001101", - "uncompressed": "jpeg", - "uncompressed_mimetype": "image/jpeg", - }, - "points_needed": 3, - "promote": null, - "slug": "course1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - }, - Object { - "id": "00000000-0000-0000-0000-000000000102", - }, - ], - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher1", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], -} -`; - -exports[`Course queries course admin returns full course on id and slug 2`] = ` -Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": null, - "course_aliases": Array [ - Object { - "course_code": "alias", - "id": "67000000-0000-0000-0000-000000000001", - }, - ], - "course_translations": Array [ - Object { - "description": "course1_description_en_US", - "id": "00000000-0000-0000-0000-000000000011", - "language": "en_US", - "link": "http://link.com", - "name": "course1_en_US", - }, - Object { - "description": "course1_description_fi_FI", - "id": "00000000-0000-0000-0000-000000000012", - "language": "fi_FI", - "link": "http:/link.fi.com", - "name": "course1_fi_FI", - }, - ], - "course_variants": Array [], - "ects": null, - "end_date": "12/31/2100", - "exercise_completions_needed": 1, - "exercises": Array [ - Object { - "deleted": false, - "id": "50000000-0000-0000-0000-000000000003", - "name": "exercise 3", - }, - ], - "has_certificate": false, - "hidden": null, - "id": Any, - "inherit_settings_from": null, - "name": "course1", - "open_university_registration_links": Array [ - Object { - "course_code": "alias", - "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", - "language": "en_US", - "link": "avoin-link", - }, - ], - "order": null, - "photo": Object { - "compressed": "webp", - "compressed_mimetype": "image/webp", - "id": "00000000-0000-0000-0000-000000001101", - "uncompressed": "jpeg", - "uncompressed_mimetype": "image/jpeg", - }, - "points_needed": 3, - "promote": null, - "slug": "course1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - }, - Object { - "id": "00000000-0000-0000-0000-000000000102", - }, - ], - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher1", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], -} -`; - -exports[`Course queries course admin should include deleted exercises if specified 1`] = ` -Object { - "automatic_completions": true, - "automatic_completions_eligible_for_ects": true, - "completions_handled_by": null, - "course_aliases": Array [ - Object { - "course_code": "alias", - "id": "67000000-0000-0000-0000-000000000001", - }, - ], - "course_translations": Array [ - Object { - "description": "course1_description_en_US", - "id": "00000000-0000-0000-0000-000000000011", - "language": "en_US", - "link": "http://link.com", - "name": "course1_en_US", - }, - Object { - "description": "course1_description_fi_FI", - "id": "00000000-0000-0000-0000-000000000012", - "language": "fi_FI", - "link": "http:/link.fi.com", - "name": "course1_fi_FI", - }, - ], - "course_variants": Array [], - "ects": null, - "end_date": "12/31/2100", - "exercise_completions_needed": 1, - "exercises": Array [ - Object { - "deleted": false, - "id": "50000000-0000-0000-0000-000000000003", - "name": "exercise 3", - }, - Object { - "deleted": true, - "id": "50000000-0000-0000-0000-000000000004", - "name": "deleted exercise 4", - }, - ], - "has_certificate": false, - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "inherit_settings_from": null, - "name": "course1", - "open_university_registration_links": Array [ - Object { - "course_code": "alias", - "id": "e3eea9b5-1ff1-47f8-94f4-269c7a092d93", - "language": "en_US", - "link": "avoin-link", - }, - ], - "order": null, - "photo": Object { - "compressed": "webp", - "compressed_mimetype": "image/webp", - "id": "00000000-0000-0000-0000-000000001101", - "uncompressed": "jpeg", - "uncompressed_mimetype": "image/jpeg", - }, - "points_needed": 3, - "promote": null, - "slug": "course1", - "start_date": "01/01/1900", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - }, - Object { - "id": "00000000-0000-0000-0000-000000000102", - }, - ], - "support_email": null, - "teacher_in_charge_email": "e@mail.com", - "teacher_in_charge_name": "teacher1", - "tier": null, - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], -} -`; - -exports[`Course queries course normal user returns correct language 1`] = ` -Object { - "description": "course1_description_en_US", - "id": Any, - "link": "http://link.com", - "name": "course1_en_US", - "slug": "course1", -} -`; - -exports[`Course queries course normal user returns course on id and slug 1`] = ` -Object { - "description": "", - "id": Any, - "link": "", - "name": "course1", - "slug": "course1", -} -`; - -exports[`Course queries course normal user returns course on id and slug 2`] = ` -Object { - "description": "", - "id": Any, - "link": "", - "name": "course1", - "slug": "course1", -} -`; - -exports[`Course queries courses filters handledBy: courses-hidden-foo 1`] = `Array []`; - -exports[`Course queries courses filters handledBy: courses-hidden-handler 1`] = ` -Array [ - "00000000-0000-0000-0000-000000000667", -] -`; - -exports[`Course queries courses filters hidden: courses-hidden-false 1`] = ` -Array [ - "00000000-0000-0000-0000-000000000001", - "00000000-0000-0000-0000-000000000002", - "00000000-0000-0000-0000-000000000666", -] -`; - -exports[`Course queries courses filters hidden: courses-hidden-null 1`] = ` -Array [ - "00000000-0000-0000-0000-000000000001", - "00000000-0000-0000-0000-000000000002", - "00000000-0000-0000-0000-000000000666", -] -`; - -exports[`Course queries courses filters hidden: courses-hidden-true 1`] = ` -Array [ - "00000000-0000-0000-0000-000000000001", - "00000000-0000-0000-0000-000000000002", - "00000000-0000-0000-0000-000000000666", - "00000000-0000-0000-0000-000000000667", - "00000000-0000-0000-0000-000000000668", -] -`; - -exports[`Course queries courses returns courses 1`] = ` -Array [ - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000022", - "language": "fi_FI", - "name": "course2_fi_FI", - }, - ], - "description": "", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000001", - "link": "", - "name": "course2", - "order": null, - "photo": null, - "promote": null, - "slug": "course2", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000011", - "language": "en_US", - "name": "course1_en_US", - }, - Object { - "id": "00000000-0000-0000-0000-000000000012", - "language": "fi_FI", - "name": "course1_fi_FI", - }, - ], - "description": "", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "link": "", - "name": "course1", - "order": null, - "photo": Object { - "compressed": "webp", - "id": "00000000-0000-0000-0000-000000001101", - "uncompressed": "jpeg", - }, - "promote": null, - "slug": "course1", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - "slug": "module2", - }, - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [], - "description": "", - "hidden": false, - "id": "00000000-0000-0000-0000-000000000666", - "link": "", - "name": "handler", - "order": null, - "photo": null, - "promote": null, - "slug": "handler", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [], - "description": "", - "hidden": true, - "id": "00000000-0000-0000-0000-000000000667", - "link": "", - "name": "handled", - "order": null, - "photo": null, - "promote": null, - "slug": "handled", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [], - "description": "", - "hidden": true, - "id": "00000000-0000-0000-0000-000000000668", - "link": "", - "name": "inherits", - "order": null, - "photo": null, - "promote": null, - "slug": "inherits", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, -] -`; - -exports[`Course queries courses returns courses filtered by language: courses-language-bogus 1`] = `Array []`; - -exports[`Course queries courses returns courses filtered by language: courses-language-en_US 1`] = ` -Array [ - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000011", - "language": "en_US", - "name": "course1_en_US", - }, - Object { - "id": "00000000-0000-0000-0000-000000000012", - "language": "fi_FI", - "name": "course1_fi_FI", - }, - ], - "description": "course1_description_en_US", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "link": "http://link.com", - "name": "course1", - "order": null, - "photo": Object { - "compressed": "webp", - "id": "00000000-0000-0000-0000-000000001101", - "uncompressed": "jpeg", - }, - "promote": null, - "slug": "course1", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - "slug": "module2", - }, - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, -] -`; - -exports[`Course queries courses returns courses filtered by language: courses-language-fi_FI 1`] = ` -Array [ - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000022", - "language": "fi_FI", - "name": "course2_fi_FI", - }, - ], - "description": "course2_description_fi_FI", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000001", - "link": "", - "name": "course2", - "order": null, - "photo": null, - "promote": null, - "slug": "course2", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000011", - "language": "en_US", - "name": "course1_en_US", - }, - Object { - "id": "00000000-0000-0000-0000-000000000012", - "language": "fi_FI", - "name": "course1_fi_FI", - }, - ], - "description": "course1_description_fi_FI", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "link": "http:/link.fi.com", - "name": "course1", - "order": null, - "photo": Object { - "compressed": "webp", - "id": "00000000-0000-0000-0000-000000001101", - "uncompressed": "jpeg", - }, - "promote": null, - "slug": "course1", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - "slug": "module2", - }, - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, -] -`; - -exports[`Course queries courses returns courses ordered: courses-order-asc 1`] = ` -Array [ - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000011", - "language": "en_US", - "name": "course1_en_US", - }, - Object { - "id": "00000000-0000-0000-0000-000000000012", - "language": "fi_FI", - "name": "course1_fi_FI", - }, - ], - "description": "", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "link": "", - "name": "course1", - "order": null, - "photo": Object { - "compressed": "webp", - "id": "00000000-0000-0000-0000-000000001101", - "uncompressed": "jpeg", - }, - "promote": null, - "slug": "course1", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - "slug": "module2", - }, - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000022", - "language": "fi_FI", - "name": "course2_fi_FI", - }, - ], - "description": "", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000001", - "link": "", - "name": "course2", - "order": null, - "photo": null, - "promote": null, - "slug": "course2", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [], - "description": "", - "hidden": true, - "id": "00000000-0000-0000-0000-000000000667", - "link": "", - "name": "handled", - "order": null, - "photo": null, - "promote": null, - "slug": "handled", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [], - "description": "", - "hidden": false, - "id": "00000000-0000-0000-0000-000000000666", - "link": "", - "name": "handler", - "order": null, - "photo": null, - "promote": null, - "slug": "handler", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [], - "description": "", - "hidden": true, - "id": "00000000-0000-0000-0000-000000000668", - "link": "", - "name": "inherits", - "order": null, - "photo": null, - "promote": null, - "slug": "inherits", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, -] -`; - -exports[`Course queries courses returns courses ordered: courses-order-desc 1`] = ` -Array [ - Object { - "course_translations": Array [], - "description": "", - "hidden": true, - "id": "00000000-0000-0000-0000-000000000668", - "link": "", - "name": "inherits", - "order": null, - "photo": null, - "promote": null, - "slug": "inherits", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [], - "description": "", - "hidden": false, - "id": "00000000-0000-0000-0000-000000000666", - "link": "", - "name": "handler", - "order": null, - "photo": null, - "promote": null, - "slug": "handler", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [], - "description": "", - "hidden": true, - "id": "00000000-0000-0000-0000-000000000667", - "link": "", - "name": "handled", - "order": null, - "photo": null, - "promote": null, - "slug": "handled", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000022", - "language": "fi_FI", - "name": "course2_fi_FI", - }, - ], - "description": "", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000001", - "link": "", - "name": "course2", - "order": null, - "photo": null, - "promote": null, - "slug": "course2", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, - Object { - "course_translations": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000011", - "language": "en_US", - "name": "course1_en_US", - }, - Object { - "id": "00000000-0000-0000-0000-000000000012", - "language": "fi_FI", - "name": "course1_fi_FI", - }, - ], - "description": "", - "hidden": null, - "id": "00000000-0000-0000-0000-000000000002", - "link": "", - "name": "course1", - "order": null, - "photo": Object { - "compressed": "webp", - "id": "00000000-0000-0000-0000-000000001101", - "uncompressed": "jpeg", - }, - "promote": null, - "slug": "course1", - "start_point": null, - "status": "Upcoming", - "study_module_order": null, - "study_module_start_point": null, - "study_modules": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000101", - "slug": "module2", - }, - Object { - "id": "00000000-0000-0000-0000-000000000102", - "slug": "module1", - }, - ], - "upcoming_active_link": false, - "user_course_settings_visibilities": Array [], - }, -] -`; - -exports[`Course queries handlerCourses returns correctly 1`] = ` -Array [ - Object { - "handles_completions_for": Array [ - Object { - "id": "00000000-0000-0000-0000-000000000667", - }, - ], - "id": "00000000-0000-0000-0000-000000000666", - }, -] -`; diff --git a/backend/graphql/Course/__test__/util.ts b/backend/graphql/Course/__test__/util.ts new file mode 100644 index 000000000..05f3e18a5 --- /dev/null +++ b/backend/graphql/Course/__test__/util.ts @@ -0,0 +1,29 @@ +export const courseInclude = { + course_tags: { + include: { + tag: { + include: { + tag_types: true, + tag_translations: true, + }, + }, + }, + }, + course_translations: true, + course_aliases: true, + course_variants: true, + exercises: true, + completions_handled_by: true, + handles_completions_for: true, + inherit_settings_from: true, + photo: true, + open_university_registration_links: true, + completion_email: true, + course_stats_email: true, + study_modules: { + include: { + study_module_translations: true, + }, + }, + services: true, +} diff --git a/backend/graphql/Course/index.ts b/backend/graphql/Course/index.ts index e052193cc..06ae979b9 100644 --- a/backend/graphql/Course/index.ts +++ b/backend/graphql/Course/index.ts @@ -1,4 +1,4 @@ -// generated Tue Sep 27 2022 11:23:58 GMT+0300 (Itä-Euroopan kesäaika) +// generated Fri Dec 02 2022 11:28:08 GMT+0200 (Itä-Euroopan normaaliaika) export * from "./input" export * from "./model" diff --git a/backend/graphql/Course/input.ts b/backend/graphql/Course/input.ts index e59ddd2fa..fbdf9494c 100644 --- a/backend/graphql/Course/input.ts +++ b/backend/graphql/Course/input.ts @@ -1,4 +1,4 @@ -import { inputObjectType } from "nexus" +import { inputObjectType, nonNull } from "nexus" export const CourseCreateArg = inputObjectType({ name: "CourseCreateArg", @@ -6,8 +6,8 @@ export const CourseCreateArg = inputObjectType({ t.string("name") t.nonNull.string("slug") t.string("ects") - t.nullable.id("photo") - t.nullable.field("new_photo", { type: "Upload" }) + t.id("photo") + t.field("new_photo", { type: "Upload" }) t.boolean("base64") t.boolean("start_point") t.boolean("promote") @@ -39,32 +39,35 @@ export const CourseCreateArg = inputObjectType({ t.int("points_needed") t.boolean("automatic_completions") t.boolean("automatic_completions_eligible_for_ects") - t.nullable.id("completion_email_id") - t.nullable.id("inherit_settings_from") - t.nullable.id("completions_handled_by") - t.nullable.boolean("has_certificate") + t.id("completion_email_id") + t.id("inherit_settings_from") + t.id("completions_handled_by") + t.boolean("has_certificate") t.list.nonNull.field("user_course_settings_visibilities", { type: "UserCourseSettingsVisibilityCreateInput", }) - t.nullable.boolean("upcoming_active_link") + t.boolean("upcoming_active_link") t.int("tier") t.int("exercise_completions_needed") t.int("points_needed") - t.nullable.id("course_stats_email_id") + t.id("course_stats_email_id") + t.list.nonNull.field("tags", { + type: nonNull("TagUpsertInput"), + }) }, }) export const CourseUpsertArg = inputObjectType({ name: "CourseUpsertArg", definition(t) { - t.nullable.id("id") + t.id("id") t.nonNull.string("name") t.nonNull.string("slug") - t.nullable.string("new_slug") + t.string("new_slug") t.string("ects") - t.nullable.id("photo") - t.nullable.field("new_photo", { type: "Upload" }) - t.nullable.boolean("delete_photo") + t.id("photo") + t.field("new_photo", { type: "Upload" }) + t.boolean("delete_photo") t.boolean("base64") t.boolean("start_point") t.boolean("promote") @@ -96,17 +99,42 @@ export const CourseUpsertArg = inputObjectType({ t.int("points_needed") t.boolean("automatic_completions") t.boolean("automatic_completions_eligible_for_ects") - t.nullable.id("completion_email_id") - t.nullable.id("inherit_settings_from") - t.nullable.id("completions_handled_by") - t.nullable.boolean("has_certificate") + t.id("completion_email_id") + t.id("inherit_settings_from") + t.id("completions_handled_by") + t.boolean("has_certificate") t.list.nonNull.field("user_course_settings_visibilities", { type: "UserCourseSettingsVisibilityUpsertInput", }) - t.nullable.boolean("upcoming_active_link") + t.boolean("upcoming_active_link") t.int("tier") t.int("exercise_completions_needed") t.int("points_needed") - t.nullable.id("course_stats_email_id") + t.id("course_stats_email_id") + t.list.nonNull.field("tags", { + type: nonNull("TagUpsertInput"), + }) + }, +}) + +export const CourseOrderByInput = inputObjectType({ + name: "CourseOrderByInput", + definition(t) { + t.field("id", { type: "SortOrder" }) + t.field("name", { type: "SortOrder" }) + t.field("slug", { type: "SortOrder" }) + t.field("ects", { type: "SortOrder" }) + t.field("start_date", { type: "SortOrder" }) + t.field("end_date", { type: "SortOrder" }) + t.field("order", { type: "SortOrder" }) + t.field("study_module_order", { type: "SortOrder" }) + t.field("points_needed", { type: "SortOrder" }) + t.field("exercise_completions_needed", { type: "SortOrder" }) + t.field("tier", { type: "SortOrder" }) + t.field("teacher_in_charge_name", { type: "SortOrder" }) + t.field("teacher_in_charge_email", { type: "SortOrder" }) + t.field("support_email", { type: "SortOrder" }) + t.field("created_at", { type: "SortOrder" }) + t.field("updated_at", { type: "SortOrder" }) }, }) diff --git a/backend/graphql/Course/model.ts b/backend/graphql/Course/model.ts index e19d83454..f39ae4079 100644 --- a/backend/graphql/Course/model.ts +++ b/backend/graphql/Course/model.ts @@ -1,4 +1,5 @@ -import { booleanArg, intArg, nullable, objectType, stringArg } from "nexus" +import { ForbiddenError } from "apollo-server-core" +import { booleanArg, intArg, list, nonNull, objectType, stringArg } from "nexus" import { Prisma } from "@prisma/client" @@ -59,6 +60,7 @@ export const Course = objectType({ t.model.handles_completions_for() t.model.course_stats_email_id() t.model.course_stats_email() + // t.model.course_tags() t.string("description") t.string("instructions") @@ -67,17 +69,16 @@ export const Course = objectType({ t.list.nonNull.field("completions", { type: "Completion", args: { - user_id: nullable(stringArg()), - user_upstream_id: nullable(intArg()), + user_id: stringArg(), + user_upstream_id: intArg(), }, authorize: isAdmin, - resolve: async (parent, args, ctx) => { - const { user_id, user_upstream_id } = args - + validate: (_, { user_id, user_upstream_id }) => { if (!user_id && !user_upstream_id) { throw new Error("needs user_id or user_upstream_id") } - + }, + resolve: async (parent, { user_id, user_upstream_id }, ctx) => { return ctx.prisma.course .findUnique({ where: { @@ -126,5 +127,85 @@ export const Course = objectType({ }) }, }) + + t.nonNull.list.nonNull.field("tags", { + type: "Tag", + args: { + language: stringArg(), + types: list(nonNull(stringArg())), + search: stringArg(), + includeHidden: booleanArg(), + }, + validate: (_, { includeHidden }, ctx) => { + if (includeHidden && !isAdmin({}, {}, ctx, {})) { + throw new ForbiddenError("no admin rights") + } + }, + resolve: async ( + parent, + { language, types, search, includeHidden }, + ctx, + ) => { + const where = {} as Prisma.CourseTagWhereInput + + if (language) { + where.tag = { + tag_translations: { + some: { + language, + }, + }, + } as Prisma.TagWhereInput + } + if (types) { + where.tag = { + ...where.tag, + tag_types: { + some: { + name: { in: types }, + }, + }, + } as Prisma.TagWhereInput + } + if (search) { + where.tag = { + ...where.tag, + tag_translations: { + some: { + ...(language && { language }), + OR: [ + { + name: { contains: search, mode: "insensitive" }, + }, + { + description: { contains: search, mode: "insensitive" }, + }, + ], + }, + }, + } as Prisma.TagWhereInput + } + if (!includeHidden) { + where.tag = { + ...where.tag, + OR: [{ hidden: false }, { hidden: null }], + } as Prisma.TagWhereInput + } + + const res = await ctx.prisma.course.findUnique({ + where: { id: parent.id }, + select: { + course_tags: { + where, + include: { + tag: true, + }, + }, + }, + }) + + return (res?.course_tags ?? []).map((ct) => ({ ...ct.tag, language })) + }, + }) }, }) diff --git a/backend/graphql/Course/mutations.ts b/backend/graphql/Course/mutations.ts index 41307331d..21f1b9036 100644 --- a/backend/graphql/Course/mutations.ts +++ b/backend/graphql/Course/mutations.ts @@ -1,23 +1,28 @@ +/* eslint-disable complexity */ import { UserInputError } from "apollo-server-express" import { omit } from "lodash" import { arg, extendType, idArg, nonNull, stringArg } from "nexus" +import { NexusGenInputs } from "nexus-typegen" -import { Course, Prisma } from "@prisma/client" +import { Course, CourseTag, Prisma, StudyModule } from "@prisma/client" import { isAdmin } from "../../accessControl" -import { DatabaseInputError } from "../../bin/lib/errors" import { Context } from "../../context" import KafkaProducer, { ProducerMessage } from "../../services/kafkaProducer" import { invalidate } from "../../services/redis" -import { notEmpty } from "../../util/notEmpty" +import { + connectOrDisconnect, + createCourseMutations, + getIds, +} from "../../util/courseMutationHelpers" +import { isNotNullOrUndefined } from "../../util/isNullOrUndefined" import { deleteImage, uploadImage } from "../Image" -const isNotNull = (value: T | null | undefined): value is T => - value !== null && value !== undefined - const nullToUndefined = (value: T | null | undefined): T | undefined => value ?? undefined +const hasId = (value: any): value is T & { id: string } => Boolean(value?.id) + export const CourseMutations = extendType({ type: "Mutation", definition(t) { @@ -34,8 +39,6 @@ export const CourseMutations = extendType({ resolve: async (_, { course }, ctx: Context) => { const { // slug, - new_photo, - base64, course_translations, open_university_registration_links, course_variants, @@ -46,19 +49,10 @@ export const CourseMutations = extendType({ user_course_settings_visibilities, completion_email_id, course_stats_email_id, + tags, } = course - let photo = null - - if (new_photo) { - const newImage = await uploadImage({ - ctx, - file: new_photo, - base64: base64 ?? false, - }) - - photo = newImage.id - } + const photo = await updatePossibleNewPhoto(course, ctx) if (study_modules?.some((s) => !s?.id && !s?.slug)) { throw new UserInputError("study modules must have id or slug") @@ -69,13 +63,14 @@ export const CourseMutations = extendType({ ...omit(course, [ "base64", "new_photo", + "tags", "completion_email_id", "course_stats_email_id", ]), name: course.name ?? "", photo: !!photo ? { connect: { id: photo } } : undefined, course_translations: { - create: course_translations?.filter(isNotNull), + create: course_translations?.filter(isNotNullOrUndefined), }, study_modules: !!study_modules ? { @@ -85,10 +80,10 @@ export const CourseMutations = extendType({ } : undefined, open_university_registration_links: { - create: open_university_registration_links?.filter(isNotNull), + create: open_university_registration_links ?? undefined, }, - course_variants: { create: course_variants?.filter(isNotNull) }, - course_aliases: { create: course_aliases?.filter(isNotNull) }, + course_variants: { create: course_variants ?? undefined }, + course_aliases: { create: course_aliases ?? undefined }, inherit_settings_from: !!inherit_settings_from ? { connect: { id: inherit_settings_from } } : undefined, @@ -96,7 +91,7 @@ export const CourseMutations = extendType({ ? { connect: { id: completions_handled_by } } : undefined, user_course_settings_visibilities: { - create: user_course_settings_visibilities?.filter(isNotNull), + create: user_course_settings_visibilities ?? undefined, }, // don't think these will be passed by parameter, but let's be sure completion_email: !!completion_email_id @@ -105,6 +100,12 @@ export const CourseMutations = extendType({ course_stats_email: !!course_stats_email_id ? { connect: { id: course_stats_email_id } } : undefined, + course_tags: { + create: tags + ?.map((tag) => tag.id) + .filter(isNotNullOrUndefined) + .map((id) => ({ tag: { connect: { id } } })), + }, }, }) @@ -134,22 +135,16 @@ export const CourseMutations = extendType({ resolve: async (_, { course }, ctx: Context) => { const { id, - new_photo, slug, new_slug, - base64, - course_translations, - open_university_registration_links, - course_variants, - course_aliases, study_modules, completion_email_id, status, delete_photo, inherit_settings_from, completions_handled_by, - user_course_settings_visibilities, course_stats_email_id, + tags, } = course let { end_date } = course @@ -157,20 +152,7 @@ export const CourseMutations = extendType({ throw new Error("slug required for update course") } - let photo = course.photo - - if (new_photo) { - const newImage = await uploadImage({ - ctx, - file: new_photo, - base64: base64 ?? false, - }) - if (photo && photo !== newImage.id) { - // TODO: do something with return value - await deleteImage({ ctx, id: photo }) - } - photo = newImage.id - } + let photo = await updatePossibleNewPhoto(course, ctx) const existingCourse = await ctx.prisma.course.findUnique({ where: { slug }, @@ -179,11 +161,16 @@ export const CourseMutations = extendType({ completions_handled_by: true, inherit_settings_from: true, user_course_settings_visibilities: true, + course_tags: true, }, }) + if (!existingCourse) { + throw new UserInputError("course not found") + } + if ( - existingCourse?.status != status && + existingCourse.status != status && status === "Ended" && end_date !== "" ) { @@ -195,53 +182,19 @@ export const CourseMutations = extendType({ photo = null } - // FIXME: I know there's probably a better way to do this - const translationMutation: - | Prisma.CourseTranslationUpdateManyWithoutCourseInput - | undefined = await createMutation({ - ctx, - slug, - data: course_translations, - field: "course_translations", - }) - - const registrationLinkMutation: - | Prisma.OpenUniversityRegistrationLinkUpdateManyWithoutCourseInput - | undefined = await createMutation({ + const updatedFields = await createCourseMutations( ctx, slug, - data: open_university_registration_links, - field: "open_university_registration_links", - }) - - const courseVariantMutation: - | Prisma.CourseVariantUpdateManyWithoutCourseInput - | undefined = await createMutation({ - ctx, - slug, - data: course_variants, - field: "course_variants", - }) - - const courseAliasMutation: - | Prisma.CourseAliasUpdateManyWithoutCourseInput - | undefined = await createMutation({ - ctx, - slug, - data: course_aliases, - field: "course_aliases", - }) - - const userCourseSettingsVisibilityMutation: - | Prisma.UserCourseSettingsVisibilityUpdateManyWithoutCourseInput - | undefined = await createMutation({ - ctx, - slug, - data: user_course_settings_visibilities, - field: "user_course_settings_visibilities", - }) - - for (const visibility of existingCourse?.user_course_settings_visibilities ?? + )([ + "course_translations", + "open_university_registration_links", + "course_variants", + "course_aliases", + "user_course_settings_visibilities", + //{ name: "course_tags", id: "tag_id" }, + ])(course) + + for (const visibility of existingCourse.user_course_settings_visibilities ?? []) { await invalidate( "usercoursesettingscount", @@ -249,48 +202,18 @@ export const CourseMutations = extendType({ ) } - // this had different logic so it's not done with the same helper - //const addedModules: StudyModuleWhereUniqueInput[] = pullAll(study_modules, existingStudyModules.map(module => module.id)) - const removedModuleIds = - existingCourse?.study_modules - ?.filter((module) => !getIds(study_modules).includes(module.id)) - .map((module) => ({ id: module.id })) ?? [] - const connectModules = - study_modules?.map((s) => ({ - ...s, - id: nullToUndefined(s?.id), - slug: nullToUndefined(s?.slug), - })) ?? [] - const studyModuleMutation: | Prisma.StudyModuleUpdateManyWithoutCoursesInput - | undefined = study_modules - ? { - connect: connectModules.length ? connectModules : undefined, - disconnect: removedModuleIds.length - ? removedModuleIds - : undefined, - } - : undefined - - const inheritMutation = inherit_settings_from - ? { - connect: { id: inherit_settings_from }, - } - : existingCourse?.inherit_settings_from - ? { - disconnect: true, // { id: existingInherit.id }, - } - : undefined - const handledMutation = completions_handled_by - ? { - connect: { id: completions_handled_by }, - } - : existingCourse?.completions_handled_by - ? { - disconnect: true, // { id: existingHandled.id }, - } - : undefined + | undefined = getStudyModuleMutation(existingCourse, study_modules) + const inheritMutation = connectOrDisconnect( + inherit_settings_from, + existingCourse.inherit_settings_from, + ) + const handledMutation = connectOrDisconnect( + completions_handled_by, + existingCourse.completions_handled_by, + ) + const courseTagMutation = getCourseTagMutation(existingCourse, tags) const updatedCourse = await ctx.prisma.course.update({ where: { @@ -307,16 +230,14 @@ export const CourseMutations = extendType({ "delete_photo", "completion_email_id", "course_stats_email_id", + "tags", ]), slug: new_slug ?? slug, end_date, // FIXME: disconnect removed photos? + ...updatedFields, photo: !!photo ? { connect: { id: photo } } : undefined, - course_translations: translationMutation, study_modules: studyModuleMutation, - open_university_registration_links: registrationLinkMutation, - course_variants: courseVariantMutation, - course_aliases: courseAliasMutation, completion_email: completion_email_id ? { connect: { id: completion_email_id } } : undefined, @@ -325,8 +246,7 @@ export const CourseMutations = extendType({ : undefined, inherit_settings_from: inheritMutation, completions_handled_by: handledMutation, - user_course_settings_visibilities: - userCourseSettingsVisibilityMutation, + course_tags: courseTagMutation, }, }) @@ -341,24 +261,33 @@ export const CourseMutations = extendType({ slug: stringArg(), }, authorize: isAdmin, - resolve: async (_, args, ctx: Context) => { - const { id, slug } = args - + validate: (_, { id, slug }) => { if (!id && !slug) { throw new UserInputError("must provide id or slug") } + }, + resolve: async (_, { id, slug }, ctx: Context) => { + const existing = await ctx.prisma.course.findUnique({ + where: { + id: id ?? undefined, + slug: slug ?? undefined, + }, + include: { + photo: true, + course_tags: true, + }, + }) - const photo = await ctx.prisma.course - .findUnique({ + if (existing?.photo) { + await deleteImage({ ctx, id: existing?.photo.id }) + } + if (existing?.course_tags?.length) { + // prisma won't allow cascade deletes until 2.26 and referentialActions + await ctx.prisma.courseTag.deleteMany({ where: { - id: id ?? undefined, - slug: slug ?? undefined, + course_id: existing.id, }, }) - .photo() - - if (photo) { - await deleteImage({ ctx, id: photo.id }) } const deletedCourse = await ctx.prisma.course.delete({ @@ -374,62 +303,92 @@ export const CourseMutations = extendType({ }, }) -type WithIdOrNull = { id?: string | null; [key: string]: any } | null -const getIds = (arr?: WithIdOrNull[] | null) => arr?.map((t) => t?.id) ?? [] +async function updatePossibleNewPhoto( + course: NexusGenInputs["CourseCreateArg"] | NexusGenInputs["CourseUpsertArg"], + ctx: Context, +) { + const { photo, new_photo, base64 } = course -function filterNotIncluded(arr1: WithIdOrNull[], arr2: WithIdOrNull[]) { - const ids1 = getIds(arr1) - const ids2 = getIds(arr2) - - const filtered = ids1.filter((id) => !ids2.includes(id)).filter(notEmpty) - - return filtered.map((id) => ({ id })) -} + if (!new_photo) { + return course.photo + } -interface ICreateMutation { - ctx: Context - slug: string - data?: T[] | null - field: keyof Prisma.Prisma__CourseClient + const newImage = await uploadImage({ + ctx, + file: new_photo, + base64: base64 ?? false, + }) + if (photo && photo !== newImage.id) { + // TODO: do something with return value + await deleteImage({ ctx, id: photo }) + } + return newImage.id } -const createMutation = async ({ - ctx, - slug, - data, - field, -}: ICreateMutation) => { - if (!data) { - return undefined +function getCourseTagMutation< + C extends Course & { course_tags: Array }, +>( + existingCourse: C, + tags?: + | ( + | NexusGenInputs["CourseCreateArg"] + | NexusGenInputs["CourseUpsertArg"] + )["tags"] + | null, +): Prisma.CourseTagUpdateManyWithoutCourseInput | undefined { + if (!tags) { + return } - let existing: T[] | undefined + const removedTagIds = + existingCourse.course_tags + ?.filter((course_tag) => !getIds(tags ?? []).includes(course_tag.tag_id)) + .map((course_tag) => ({ + course_id: existingCourse.id, + tag_id: course_tag.tag_id, + })) ?? [] + const connectTags = (tags ?? []).filter(hasId).map((t) => ({ + course_id_tag_id: { + course_id: existingCourse.id, + tag_id: t.id, + }, + })) - try { - // @ts-ignore: can't be arsed to do the typing, works - existing = await ctx.prisma.course.findUnique({ where: { slug } })[field]() - } catch (e: any) { - throw new DatabaseInputError(`error creating mutation`, { field, slug }, e) + return { + connect: connectTags.length ? connectTags : undefined, + deleteMany: removedTagIds.length ? removedTagIds : undefined, + // can't just disconnect as it would violate null constraint on course_id } +} - const newOnes = (data || []) - .filter(hasNotId) // (t) => !t.id - .map((t) => ({ ...t, id: undefined })) - const updated = (data || []) - .filter(hasId) // (t) => !!t.id) - .map((t) => ({ - where: { id: t.id }, - data: t, //{ ...t, id: undefined }, - })) - const removed = filterNotIncluded(existing ?? [], data) +function getStudyModuleMutation< + C extends Course & { study_modules: Array }, +>( + existingCourse: C, + study_modules?: + | ( + | NexusGenInputs["CourseCreateArg"] + | NexusGenInputs["CourseUpsertArg"] + )["study_modules"] + | null, +): Prisma.StudyModuleUpdateManyWithoutCoursesInput | undefined { + if (!study_modules) { + return + } + + const removedModuleIds = + existingCourse.study_modules + ?.filter((module) => !getIds(study_modules ?? []).includes(module.id)) + .map((module) => ({ id: module.id })) ?? [] + const connectModules = + study_modules?.map((s) => ({ + ...s, + id: nullToUndefined(s?.id), + slug: nullToUndefined(s?.slug), + })) ?? [] return { - create: newOnes.length ? newOnes : undefined, - updateMany: updated.length ? updated : undefined, - deleteMany: removed.length ? removed : undefined, + connect: connectModules.length ? connectModules : undefined, + disconnect: removedModuleIds.length ? removedModuleIds : undefined, } } - -const hasId = (data: T): data is T & { id: string } => - Boolean(data?.id) -const hasNotId = (data: T) => !hasId(data) diff --git a/backend/graphql/Course/queries.ts b/backend/graphql/Course/queries.ts index d8817c0c7..b6ee91d02 100644 --- a/backend/graphql/Course/queries.ts +++ b/backend/graphql/Course/queries.ts @@ -7,20 +7,25 @@ import { idArg, list, nonNull, - nullable, stringArg, } from "nexus" -import { Course, CourseTranslation, Prisma } from "@prisma/client" +import { + Course, + CourseTag, + CourseTranslation, + Prisma, + Tag, +} from "@prisma/client" import { isAdmin, isUser, or, Role } from "../../accessControl" -import { filterNull, getCourseOrAlias } from "../../util/db-functions" +import { filterNullRecursive, getCourseOrAlias } from "../../util/db-functions" import { notEmpty } from "../../util/notEmpty" export const CourseQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("course", { + t.field("course", { type: "Course", args: { slug: stringArg(), @@ -36,76 +41,110 @@ export const CourseQueries = extendType({ throw new UserInputError("must provide id or slug") } - const courseQuery: Prisma.CourseFindUniqueArgs = { + const query = { where: { slug: slug ?? undefined, id: id ?? undefined, }, - // TODO: limit these in the model - ...(ctx.role !== Role.ADMIN && { + include: { + course_tags: { + include: { + tag: true, + }, + }, + ...(language && { + course_translations: { + where: { + language, + }, + }, + course_tags: { + where: { + tag: { + tag_translations: { + some: { + language, + }, + }, + }, + }, + include: { + tag: true, + }, + }, + }), + }, + } + + // TODO: limit these in the model + /*...(ctx.role !== Role.ADMIN && { select: { id: true, slug: true, name: true, }, - }), - } + }),*/ + const course = await getCourseOrAlias(ctx)(query) - const course = await getCourseOrAlias(ctx)(courseQuery) - - if (!course) { + if (!course || (course.hidden && ctx.role !== Role.ADMIN)) { throw new Error("course not found") } - let description = "" - let link = "" - let name = course.name + const returnedCourse = { + ...omit(course, "course_tags"), + description: "", + link: "", + tags: (course.course_tags ?? []).map((ct) => ct.tag), // [] as Array<{ id: string; language?: string }>, + } if (language) { - const course_translation = - await ctx.prisma.courseTranslation.findFirst({ - where: { - course_id: course.id, - language, - }, - }) + const { course_translations, course_tags } = + course as typeof course & { + course_translations?: Array + } + const course_translation = course_translations?.[0] if (!course_translation) { if (!translationFallback) { return Promise.resolve(null) } } else { - description = course_translation.description ?? "" - link = course_translation.link ?? "" - name = course_translation.name + returnedCourse.description = course_translation.description ?? "" + returnedCourse.link = course_translation.link ?? "" + returnedCourse.name = course_translation.name } - } - return { - ...course, - name, - description, - link, + returnedCourse.tags = + course_tags?.map((course_tag) => course_tag.tag) ?? [] } - }, - }) - t.crud.courses({ - ordering: true, + return returnedCourse + }, }) t.list.nonNull.field("courses", { type: "Course", args: { - orderBy: arg({ type: "CourseOrderByInput" }), + orderBy: arg({ type: "CourseOrderByWithRelationInput" }), language: stringArg(), - search: nullable(stringArg()), - hidden: nullable(booleanArg({ default: true })), - handledBy: nullable(stringArg()), - status: nullable(list(nonNull(arg({ type: "CourseStatus" })))), + search: stringArg(), + hidden: booleanArg({ default: true }), + handledBy: stringArg(), + status: list(nonNull(arg({ type: "CourseStatus" }))), + tags: list(nonNull(stringArg())), + tag_types: list(nonNull(stringArg())), }, resolve: async (_, args, ctx) => { - const { orderBy, language, search, hidden, handledBy, status } = args + const { + orderBy, + language, + search, + hidden, + handledBy, + status, + tags, + tag_types, + } = args const searchQuery: Prisma.Enumerable = [] @@ -168,15 +207,62 @@ export const CourseQueries = extendType({ status: { in: status }, }) } + // TODO: if we want a filter that is strict (i.e. all tags must be present) + // then we may need a raw query or just do that filtering in the frontend + if (tags) { + searchQuery.push({ + course_tags: { + some: { + tag: { + is: { + tag_translations: { + some: { + language: language ?? undefined, + name: { in: tags }, + }, + }, + }, + }, + }, + }, + }) + } + + if (tag_types) { + searchQuery.push({ + course_tags: { + some: { + tag: { + is: { + tag_types: { + some: { + name: { in: tag_types }, + }, + }, + }, + }, + }, + }, + }) + } - const courses: (Course & { - course_translations?: CourseTranslation[] - })[] = await ctx.prisma.course.findMany({ - orderBy: - (filterNull(orderBy) as Prisma.CourseOrderByInput) ?? undefined, + const courses: Array< + Course & { + course_translations?: Array + course_tags?: Array + } + > = await ctx.prisma.course.findMany({ + orderBy: filterNullRecursive(orderBy) ?? undefined, where: { AND: searchQuery, }, + include: { + course_tags: { + include: { + tag: true, + }, + }, + }, ...(language ? { include: { @@ -185,6 +271,21 @@ export const CourseQueries = extendType({ language: { equals: language }, }, }, + course_tags: { + // TODO: is this needed? + where: { + tag: { + tag_translations: { + some: { + language, + }, + }, + }, + }, + include: { + tag: true, + }, + }, }, } : {}), @@ -196,15 +297,25 @@ export const CourseQueries = extendType({ return null } return { - ...omit(course, "course_translations"), + ...omit(course, ["course_translations", "course_tags"]), description: course?.course_translations?.[0]?.description ?? "", link: course?.course_translations?.[0]?.link ?? "", + tags: (course.course_tags ?? []).map((course_tag) => ({ + ...course_tag.tag, + language, + })), } }) .filter(notEmpty) // TODO: (?) provide proper typing - return filtered as (Course & { description: string; link: string })[] + return filtered as Array< + Course & { + description: string + link: string + tags?: Array<{ id: string; language?: string }> + } + > }, }) diff --git a/backend/graphql/CourseAlias.ts b/backend/graphql/CourseAlias.ts index 4d1c80a75..53b6089ee 100644 --- a/backend/graphql/CourseAlias.ts +++ b/backend/graphql/CourseAlias.ts @@ -24,7 +24,7 @@ export const CourseAlias = objectType({ export const CourseAliasCreateInput = inputObjectType({ name: "CourseAliasCreateInput", definition(t) { - t.nullable.id("course") + t.id("course") t.nonNull.string("course_code") }, }) @@ -32,8 +32,8 @@ export const CourseAliasCreateInput = inputObjectType({ export const CourseAliasUpsertInput = inputObjectType({ name: "CourseAliasUpsertInput", definition(t) { - t.nullable.id("id") - t.nullable.id("course") + t.id("id") + t.id("course") t.nonNull.string("course_code") }, }) diff --git a/backend/graphql/CourseTag.ts b/backend/graphql/CourseTag.ts new file mode 100644 index 000000000..78ab5976c --- /dev/null +++ b/backend/graphql/CourseTag.ts @@ -0,0 +1,227 @@ +import { ForbiddenError, UserInputError } from "apollo-server-core" +import { + booleanArg, + extendType, + idArg, + inputObjectType, + list, + nonNull, + objectType, + stringArg, +} from "nexus" + +import { Prisma, Tag } from "@prisma/client" + +import { isAdmin, Role } from "../accessControl" + +export const CourseTag = objectType({ + name: "CourseTag", + definition(t) { + t.model.course_id() + t.model.tag_id() + t.model.created_at() + t.model.updated_at() + t.model.course() + + t.field("tag", { + type: "Tag", + // @ts-ignore: language exists + resolve: async ({ language, tag_id }, _args, ctx) => { + const tag = await ctx.prisma.tag.findUnique({ + where: { id: tag_id }, + }) + + return { ...tag, language } as Tag + }, + }) + t.string("language") // passed down + }, +}) + +export const CourseTagCreateOrUpsertInput = inputObjectType({ + name: "CourseTagCreateOrUpsertInput", + definition(t) { + t.nonNull.id("course_id") + t.nonNull.id("tag_id") + t.field("tag", { + type: "TagUpsertInput", + }) + }, +}) + +export const CourseTagCreateOrUpsertWithoutCourseIdInput = inputObjectType({ + name: "CourseTagCreateOrUpsertWithoutCourseIdInput", + definition(t) { + t.nonNull.id("tag_id") + t.field("tag", { + type: "TagUpsertInput", + }) + }, +}) + +export const CourseTagQueries = extendType({ + type: "Query", + definition(t) { + t.list.nonNull.field("courseTags", { + type: "CourseTag", + args: { + course_id: idArg(), + course_slug: stringArg(), + tag_types: list(nonNull(stringArg())), + tag_id: idArg(), + language: stringArg(), + includeHidden: booleanArg(), + }, + validate: (_, { course_id, course_slug, includeHidden }, ctx) => { + if (course_id && course_slug) { + throw new UserInputError( + "provide only one of course_id or course_slug", + ) + } + if (includeHidden && ctx.role !== Role.ADMIN) { + throw new ForbiddenError("admins only") + } + }, + resolve: async ( + _, + { course_id, course_slug, tag_id, language, tag_types, includeHidden }, + ctx, + ) => { + let _course_id = course_id + + if (course_slug) { + const course = await ctx.prisma.course.findUnique({ + where: { slug: course_slug }, + }) + _course_id = course?.id + } + + const where = { + course_id: _course_id ?? undefined, + tag_id: tag_id ?? undefined, + } as Prisma.CourseTagWhereInput + + if (language) { + where.tag = { + tag_translations: { + some: { + language, + }, + }, + } + } + if (tag_types?.length) { + where.tag = { + ...where.tag, + tag_types: { + some: { + name: { + in: tag_types, + }, + }, + }, + } as Prisma.TagWhereInput + } + if (!includeHidden) { + where.tag = { + ...where.tag, + OR: [{ hidden: false }, { hidden: null }], + } as Prisma.TagWhereInput + } + + const res = await ctx.prisma.courseTag.findMany({ + where, + }) + + return res.map((courseTag) => ({ ...courseTag, language })) + }, + }) + }, +}) + +export const CourseTagMutations = extendType({ + type: "Mutation", + definition(t) { + t.nonNull.field("addCourseTag", { + type: "CourseTag", + args: { + course_id: idArg(), + course_slug: stringArg(), + tag_id: idArg(), + tag_name: stringArg(), + }, + authorize: isAdmin, + validate: (_, { course_id, course_slug, tag_id, tag_name }) => { + if (course_id && course_slug) { + throw new UserInputError( + "provide only one of course_id or course_slug", + ) + } + if (tag_id && tag_name) { + throw new UserInputError("provide only one of tag_id or tag_name") + } + if (!tag_id && !tag_name) { + throw new UserInputError("provide either tag_id or tag_name") + } + }, + resolve: async (_, { course_id, course_slug, tag_id, tag_name }, ctx) => { + let _course_id = course_id + + if (course_slug) { + const course = await ctx.prisma.course.findUnique({ + where: { slug: course_slug }, + }) + _course_id = course?.id + } + if (!_course_id) { + throw new UserInputError("course not found") + } + + let _tag_id = tag_id + + if (tag_name) { + const tag = await ctx.prisma.tag.findFirst({ + where: { + tag_translations: { + some: { + name: tag_name, + }, + }, + }, + }) + _tag_id = tag?.id + } + + if (!_tag_id) { + throw new UserInputError("tag not found") + } + + return ctx.prisma.courseTag.create({ + data: { + course_id: _course_id, + tag_id: _tag_id, + }, + }) + }, + }) + + t.nonNull.field("deleteCourseTag", { + type: "CourseTag", + args: { + course_id: nonNull(idArg()), + tag_id: nonNull(idArg()), + }, + authorize: isAdmin, + resolve: async (_, { course_id, tag_id }, ctx) => { + return ctx.prisma.courseTag.delete({ + where: { + course_id_tag_id: { + course_id, + tag_id, + }, + }, + }) + }, + }) + }, +}) diff --git a/backend/graphql/CourseTranslation.ts b/backend/graphql/CourseTranslation.ts index 0b0ac531f..cb78ea5c8 100644 --- a/backend/graphql/CourseTranslation.ts +++ b/backend/graphql/CourseTranslation.ts @@ -31,22 +31,22 @@ export const CourseTranslationCreateInput = inputObjectType({ t.nonNull.string("name") t.nonNull.string("language") t.nonNull.string("description") - t.nullable.string("link") - t.nullable.id("course") - t.nullable.string("instructions") + t.string("link") + t.id("course") + t.string("instructions") }, }) export const CourseTranslationUpsertInput = inputObjectType({ name: "CourseTranslationUpsertInput", definition(t) { - t.nullable.id("id") + t.id("id") t.nonNull.string("name") t.nonNull.string("language") t.nonNull.string("description") - t.nullable.string("link") - t.nullable.id("course") - t.nullable.string("instructions") + t.string("link") + t.id("course") + t.string("instructions") }, }) diff --git a/backend/graphql/CourseVariant.ts b/backend/graphql/CourseVariant.ts index d855918b6..f30c052b1 100644 --- a/backend/graphql/CourseVariant.ts +++ b/backend/graphql/CourseVariant.ts @@ -25,28 +25,28 @@ export const CourseVariant = objectType({ export const CourseVariantCreateInput = inputObjectType({ name: "CourseVariantCreateInput", definition(t) { - t.nullable.id("course") + t.id("course") t.nonNull.string("slug") - t.nullable.string("description") - t.nullable.string("instructions") + t.string("description") + t.string("instructions") }, }) export const CourseVariantUpsertInput = inputObjectType({ name: "CourseVariantUpsertInput", definition(t) { - t.nullable.id("id") - t.nullable.id("course") + t.id("id") + t.id("course") t.nonNull.string("slug") - t.nullable.string("description") - t.nullable.string("instructions") + t.string("description") + t.string("instructions") }, }) export const CourseVariantQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("courseVariant", { + t.field("courseVariant", { type: "CourseVariant", args: { id: nonNull(idArg()), diff --git a/backend/graphql/EmailTemplate.ts b/backend/graphql/EmailTemplate.ts index 459b1395c..98832566b 100644 --- a/backend/graphql/EmailTemplate.ts +++ b/backend/graphql/EmailTemplate.ts @@ -34,7 +34,7 @@ export const EmailTemplate = objectType({ export const EmailTemplateQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("email_template", { + t.field("email_template", { type: "EmailTemplate", args: { id: nonNull(idArg()), diff --git a/backend/graphql/Exercise.ts b/backend/graphql/Exercise.ts index 3d6d9602f..356144b13 100644 --- a/backend/graphql/Exercise.ts +++ b/backend/graphql/Exercise.ts @@ -5,12 +5,12 @@ import { idArg, intArg, nonNull, - nullable, objectType, stringArg, } from "nexus" import { isAdmin, Role } from "../accessControl" +import { filterNullRecursive } from "../util/db-functions" import { notEmpty } from "../util/notEmpty" import { Context } from "/context" @@ -35,13 +35,10 @@ export const Exercise = objectType({ t.list.nonNull.field("exercise_completions", { type: "ExerciseCompletion", args: { - orderBy: nullable( - arg({ - // FIXME? - type: "ExerciseCompletionOrderByInput", - }), - ), - user_id: nullable(idArg()), + orderBy: arg({ + type: "ExerciseCompletionOrderByWithRelationInput", + }), + user_id: idArg(), }, resolve: async (parent, args, ctx: Context) => { const { orderBy, user_id: user_id_arg } = args @@ -61,7 +58,7 @@ export const Exercise = objectType({ orderBy: [ { timestamp: "desc" }, { updated_at: "desc" }, - orderBy, + filterNullRecursive(orderBy), ].filter(notEmpty), }) }, @@ -72,7 +69,7 @@ export const Exercise = objectType({ export const ExerciseQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("exercise", { + t.field("exercise", { type: "Exercise", args: { id: nonNull(idArg()), diff --git a/backend/graphql/ExerciseCompletion.ts b/backend/graphql/ExerciseCompletion.ts index d68ef9077..15743ffe4 100644 --- a/backend/graphql/ExerciseCompletion.ts +++ b/backend/graphql/ExerciseCompletion.ts @@ -1,4 +1,12 @@ -import { arg, extendType, idArg, intArg, nonNull, objectType } from "nexus" +import { + arg, + extendType, + idArg, + inputObjectType, + intArg, + nonNull, + objectType, +} from "nexus" import { isAdmin } from "../accessControl" @@ -20,10 +28,23 @@ export const ExerciseCompletion = objectType({ }, }) +export const ExerciseCompletionOrderByInput = inputObjectType({ + name: "ExerciseCompletionOrderByInput", + definition(t) { + t.field("id", { type: "SortOrder" }) + t.field("created_at", { type: "SortOrder" }) + t.field("updated_at", { type: "SortOrder" }) + t.field("exercise_id", { type: "SortOrder" }) + t.field("n_points", { type: "SortOrder" }) + t.field("timestamp", { type: "SortOrder" }) + t.field("user_id", { type: "SortOrder" }) + }, +}) + export const ExerciseCompletionQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("exerciseCompletion", { + t.field("exerciseCompletion", { type: "ExerciseCompletion", args: { id: nonNull(idArg()), diff --git a/backend/graphql/OpenUniversityRegistrationLink.ts b/backend/graphql/OpenUniversityRegistrationLink.ts index ddd06499c..4de2eeecb 100644 --- a/backend/graphql/OpenUniversityRegistrationLink.ts +++ b/backend/graphql/OpenUniversityRegistrationLink.ts @@ -22,14 +22,14 @@ export const OpenUniversityRegistrationLink = objectType({ t.model.link() t.model.start_date() t.model.stop_date() - t.nullable.field("tiers", { + t.nonNull.list.nonNull.field("tiers", { type: "Json", resolve: async (parent, _args, ctx) => { const res = await ctx.prisma.openUniversityRegistrationLink.findUnique({ where: { id: parent.id }, select: { tiers: true }, }) - return (res?.tiers as any) || [] + return (res?.tiers as any[]) || [] }, }) }, @@ -40,8 +40,8 @@ export const OpenUniversityRegistrationLinkCreateInput = inputObjectType({ definition(t) { t.nonNull.string("course_code") t.nonNull.string("language") - t.nullable.string("link") - t.nullable.field("tiers", { type: "Json" }) + t.string("link") + t.list.nonNull.field("tiers", { type: "Json" }) t.field("start_date", { type: "DateTime" }) t.field("stop_date", { type: "DateTime" }) }, @@ -50,11 +50,11 @@ export const OpenUniversityRegistrationLinkCreateInput = inputObjectType({ export const OpenUniversityRegistrationLinkUpsertInput = inputObjectType({ name: "OpenUniversityRegistrationLinkUpsertInput", definition(t) { - t.nullable.id("id") + t.id("id") t.nonNull.string("course_code") t.nonNull.string("language") - t.nullable.string("link") - t.nullable.field("tiers", { type: "Json" }) + t.string("link") + t.list.nonNull.field("tiers", { type: "Json" }) t.field("start_date", { type: "DateTime" }) t.field("stop_date", { type: "DateTime" }) }, @@ -63,7 +63,7 @@ export const OpenUniversityRegistrationLinkUpsertInput = inputObjectType({ export const OpenUniversityRegistrationLinkQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("openUniversityRegistrationLink", { + t.field("openUniversityRegistrationLink", { type: "OpenUniversityRegistrationLink", args: { id: nonNull(idArg()), diff --git a/backend/graphql/Organization.ts b/backend/graphql/Organization.ts index 95444113a..e4163b5d6 100644 --- a/backend/graphql/Organization.ts +++ b/backend/graphql/Organization.ts @@ -7,14 +7,13 @@ import { booleanArg, extendType, idArg, + inputObjectType, intArg, nonNull, objectType, stringArg, } from "nexus" -import { Prisma } from "@prisma/client" - import { isAdmin, Role } from "../accessControl" import { Context } from "../context" import { filterNull } from "../util/db-functions" @@ -54,6 +53,22 @@ export const Organization = objectType({ }, }) +export const OrganizationOrderByInput = inputObjectType({ + name: "OrganizationOrderByInput", + definition(t) { + t.field("contact_information", { type: "SortOrder" }) + t.field("created_at", { type: "SortOrder" }) + t.field("email", { type: "SortOrder" }) + t.field("id", { type: "SortOrder" }) + t.field("phone", { type: "SortOrder" }) + t.field("slug", { type: "SortOrder" }) + t.field("tmc_created_at", { type: "SortOrder" }) + t.field("tmc_updated_at", { type: "SortOrder" }) + t.field("updated_at", { type: "SortOrder" }) + t.field("website", { type: "SortOrder" }) + }, +}) + const organizationPermission = ( _: any, args: any, @@ -68,7 +83,7 @@ const organizationPermission = ( export const OrganizationQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("organization", { + t.field("organization", { type: "Organization", args: { id: idArg(), @@ -88,19 +103,13 @@ export const OrganizationQueries = extendType({ }, }) - t.crud.organizations({ - ordering: true, - pagination: true, - authorize: organizationPermission, - }) - t.list.nonNull.field("organizations", { type: "Organization", args: { take: intArg(), skip: intArg(), cursor: arg({ type: "OrganizationWhereUniqueInput" }), - orderBy: arg({ type: "OrganizationOrderByInput" }), + orderBy: arg({ type: "OrganizationOrderByWithRelationInput" }), hidden: booleanArg(), }, authorize: organizationPermission, @@ -115,9 +124,7 @@ export const OrganizationQueries = extendType({ id: cursor.id ?? undefined, } : undefined, - orderBy: - (filterNull(orderBy) as Prisma.OrganizationOrderByInput) ?? - undefined, + orderBy: filterNull(orderBy) ?? undefined, where: { hidden, }, diff --git a/backend/graphql/Progress.ts b/backend/graphql/Progress.ts index b9944a309..193cf587b 100644 --- a/backend/graphql/Progress.ts +++ b/backend/graphql/Progress.ts @@ -3,10 +3,10 @@ import { objectType } from "nexus" export const Progress = objectType({ name: "Progress", definition(t) { - t.nullable.field("course", { type: "Course" }) + t.field("course", { type: "Course" }) t.field("user", { type: "User" }) - t.nullable.field("user_course_progress", { + t.field("user_course_progress", { type: "UserCourseProgress", resolve: async (parent, _, ctx) => { const course_id = parent.course?.id diff --git a/backend/graphql/Service.ts b/backend/graphql/Service.ts index 5cdf7e9e4..38bc88872 100644 --- a/backend/graphql/Service.ts +++ b/backend/graphql/Service.ts @@ -19,7 +19,7 @@ export const Service = objectType({ export const ServiceQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("service", { + t.field("service", { type: "Service", args: { service_id: nonNull(idArg()), diff --git a/backend/graphql/StudyModule/index.ts b/backend/graphql/StudyModule/index.ts index e052193cc..06ae979b9 100644 --- a/backend/graphql/StudyModule/index.ts +++ b/backend/graphql/StudyModule/index.ts @@ -1,4 +1,4 @@ -// generated Tue Sep 27 2022 11:23:58 GMT+0300 (Itä-Euroopan kesäaika) +// generated Fri Dec 02 2022 11:28:08 GMT+0200 (Itä-Euroopan normaaliaika) export * from "./input" export * from "./model" diff --git a/backend/graphql/StudyModule/input.ts b/backend/graphql/StudyModule/input.ts index 34971d411..b30de14b1 100644 --- a/backend/graphql/StudyModule/input.ts +++ b/backend/graphql/StudyModule/input.ts @@ -4,10 +4,10 @@ export const StudyModuleCreateArg = inputObjectType({ name: "StudyModuleCreateArg", definition(t) { t.nonNull.string("slug") - t.nullable.string("name") - t.nullable.string("image") - t.nullable.int("order") - t.list.nullable.field("study_module_translations", { + t.string("name") + t.string("image") + t.int("order") + t.list.nonNull.field("study_module_translations", { type: "StudyModuleTranslationUpsertInput", }) }, @@ -16,14 +16,25 @@ export const StudyModuleCreateArg = inputObjectType({ export const StudyModuleUpsertArg = inputObjectType({ name: "StudyModuleUpsertArg", definition(t) { - t.nullable.id("id") + t.id("id") t.nonNull.string("slug") - t.nullable.string("new_slug") - t.nullable.string("name") - t.nullable.string("image") - t.nullable.int("order") - t.list.nullable.field("study_module_translations", { + t.string("new_slug") + t.string("name") + t.string("image") + t.int("order") + t.list.nonNull.field("study_module_translations", { type: "StudyModuleTranslationUpsertInput", }) }, }) + +export const StudyModuleOrderByInput = inputObjectType({ + name: "StudyModuleOrderByInput", + definition(t) { + t.field("id", { type: "SortOrder" }) + t.field("slug", { type: "SortOrder" }) + t.field("name", { type: "SortOrder" }) + t.field("image", { type: "SortOrder" }) + t.field("order", { type: "SortOrder" }) + }, +}) diff --git a/backend/graphql/StudyModule/model.ts b/backend/graphql/StudyModule/model.ts index 7acdc2774..e3bccc854 100644 --- a/backend/graphql/StudyModule/model.ts +++ b/backend/graphql/StudyModule/model.ts @@ -1,7 +1,7 @@ import { omit } from "lodash" import { arg, objectType, stringArg } from "nexus" -import { Course, CourseTranslation, Prisma } from "@prisma/client" +import { Course, CourseTranslation } from "@prisma/client" import { filterNull } from "../../util/db-functions" @@ -22,7 +22,7 @@ export const StudyModule = objectType({ t.list.nonNull.field("courses", { type: "Course", args: { - orderBy: arg({ type: "CourseOrderByInput" }), + orderBy: arg({ type: "CourseOrderByWithRelationInput" }), language: stringArg(), }, resolve: async (parent, args, ctx) => { @@ -35,8 +35,7 @@ export const StudyModule = objectType({ where: { id: parent.id }, }) .courses({ - orderBy: - (filterNull(orderBy) as Prisma.CourseOrderByInput) ?? undefined, + orderBy: filterNull(orderBy) ?? undefined, ...(language ? { include: { diff --git a/backend/graphql/StudyModule/mutations.ts b/backend/graphql/StudyModule/mutations.ts index 5e4ad6c3e..db2db8102 100644 --- a/backend/graphql/StudyModule/mutations.ts +++ b/backend/graphql/StudyModule/mutations.ts @@ -1,6 +1,6 @@ import { UserInputError } from "apollo-server-express" import { omit } from "lodash" -import { arg, extendType, idArg, nonNull, nullable, stringArg } from "nexus" +import { arg, extendType, idArg, nonNull, stringArg } from "nexus" import { Prisma } from "@prisma/client" @@ -60,16 +60,16 @@ export const StudyModuleMutations = extendType({ const existingTranslations = await ctx.prisma.studyModule .findUnique({ where: { slug } }) .study_module_translations() - const newTranslations = (study_module_translations || []) + const newTranslations = (study_module_translations ?? []) .filter((t) => !t?.id) .map((t) => ({ ...t, id: undefined })) - const updatedTranslations = (study_module_translations || []) + const updatedTranslations = (study_module_translations ?? []) .filter((t) => !!t?.id) .map((t) => ({ where: { id: t?.id }, data: { ...t, id: undefined } })) - const existingTranslationIds = (existingTranslations || []).map( + const existingTranslationIds = (existingTranslations ?? []).map( (t) => t.id, ) - const moduleTranslationIds = (study_module_translations || []).map( + const moduleTranslationIds = (study_module_translations ?? []).map( (t) => t?.id, ) const removedTranslationIds = existingTranslationIds @@ -109,17 +109,16 @@ export const StudyModuleMutations = extendType({ t.field("deleteStudyModule", { type: "StudyModule", args: { - id: nullable(idArg()), + id: idArg(), slug: stringArg(), }, authorize: isAdmin, - resolve: async (_, args, ctx) => { - const { id, slug } = args - + validate: (_, { id, slug }) => { if (!id && !slug) { - throw "must have at least id or slug" + throw new UserInputError("must provide id or slug") } - + }, + resolve: async (_, { id, slug }, ctx) => { const deletedModule = await ctx.prisma.studyModule.delete({ where: { id: id ?? undefined, diff --git a/backend/graphql/StudyModule/queries.ts b/backend/graphql/StudyModule/queries.ts index ce03d6e1a..9e440a779 100644 --- a/backend/graphql/StudyModule/queries.ts +++ b/backend/graphql/StudyModule/queries.ts @@ -2,7 +2,7 @@ import { UserInputError } from "apollo-server-express" import { omit } from "lodash" import { arg, booleanArg, extendType, idArg, nonNull, stringArg } from "nexus" -import { Prisma, StudyModule, StudyModuleTranslation } from "@prisma/client" +import { StudyModule, StudyModuleTranslation } from "@prisma/client" import { isAdmin, isUser, or, Role } from "../../accessControl" import { filterNull } from "../../util/db-functions" @@ -10,7 +10,7 @@ import { filterNull } from "../../util/db-functions" export const StudyModuleQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("study_module", { + t.field("study_module", { type: "StudyModule", args: { id: idArg(), @@ -19,12 +19,13 @@ export const StudyModuleQueries = extendType({ translationFallback: booleanArg({ default: false }), }, authorize: or(isAdmin, isUser), - resolve: async (_, args, ctx) => { - const { id, slug, language, translationFallback } = args - + validate: (_, { id, slug }) => { if (!id && !slug) { throw new UserInputError("must provide id or slug") } + }, + resolve: async (_, args, ctx) => { + const { id, slug, language, translationFallback } = args const study_module: | (StudyModule & { @@ -88,16 +89,14 @@ export const StudyModuleQueries = extendType({ t.list.nonNull.field("study_modules", { type: "StudyModule", args: { - orderBy: arg({ type: "StudyModuleOrderByInput" }), + orderBy: arg({ type: "StudyModuleOrderByWithRelationInput" }), language: stringArg(), }, resolve: async (_, { orderBy, language }, ctx) => { const modules: (StudyModule & { study_module_translations?: StudyModuleTranslation[] })[] = await ctx.prisma.studyModule.findMany({ - orderBy: - (filterNull(orderBy) as Prisma.StudyModuleOrderByInput) ?? - undefined, + orderBy: filterNull(orderBy) ?? undefined, ...(language ? { include: { diff --git a/backend/graphql/StudyModuleTranslation.ts b/backend/graphql/StudyModuleTranslation.ts index 88408ee36..f56315f53 100644 --- a/backend/graphql/StudyModuleTranslation.ts +++ b/backend/graphql/StudyModuleTranslation.ts @@ -29,18 +29,18 @@ export const StudyModuleTranslationCreateInput = inputObjectType({ t.nonNull.string("name") t.nonNull.string("language") t.nonNull.string("description") - t.nullable.id("study_module") + t.id("study_module") }, }) export const StudyModuleTranslationUpsertInput = inputObjectType({ name: "StudyModuleTranslationUpsertInput", definition(t) { - t.nullable.id("id") + t.id("id") t.nonNull.string("name") t.nonNull.string("language") t.nonNull.string("description") - t.nullable.id("study_module") + t.id("study_module") }, }) @@ -51,13 +51,6 @@ export const StudyModuleTranslationQueries = extendType({ pagination: false, authorize: isAdmin, }) - /*t.list.field("StudyModuleTranslations", { - type: "study_module_translation", - resolve: (_, __, ctx) => { - // checkAccess(ctx, { allowOrganizations: false }) - return ctx.prisma.study_module_translation.findMany() - }, - })*/ }, }) diff --git a/backend/graphql/Tag.ts b/backend/graphql/Tag.ts new file mode 100644 index 000000000..d3753d5c7 --- /dev/null +++ b/backend/graphql/Tag.ts @@ -0,0 +1,309 @@ +import { ForbiddenError, UserInputError } from "apollo-server-core" +import { omit } from "lodash" +import { + arg, + booleanArg, + extendType, + idArg, + inputObjectType, + list, + nonNull, + objectType, + stringArg, +} from "nexus" + +import { Prisma, Tag as TagType } from "@prisma/client" + +import { isAdmin, Role } from "../accessControl" +import { isNotNullOrUndefined } from "../util/isNullOrUndefined" + +const wrapLanguage = + (language?: null | string) => + (tag: TagType): TagType & { language?: string } => ({ + ...tag, + language: language ?? undefined, + }) + +export const Tag = objectType({ + name: "Tag", + definition(t) { + t.model.id() + t.model.hidden() + t.model.tag_types() + t.model.tag_translations() + t.model.course_tags() + t.model.created_at() + t.model.updated_at() + + t.string("language") // passed down + t.string("name", { + // @ts-ignore: language exists + resolve: async ({ id, language }, _args, ctx) => { + if (!language) { + return null + } + const name = await ctx.prisma.tag + .findUnique({ + where: { id }, + }) + .tag_translations({ + where: { language }, + }) + + return name[0]?.name ?? null + }, + }) + t.string("description", { + // @ts-ignore: language exists + resolve: async ({ id, language }, _args, ctx) => { + if (!language) { + return null + } + const name = await ctx.prisma.tag + .findUnique({ + where: { id }, + }) + .tag_translations({ + where: { language }, + }) + + return name[0]?.description ?? null + }, + }) + t.list.nonNull.string("types", { + resolve: async ({ id }, _args, ctx) => { + const types = await ctx.prisma.tag + .findUnique({ where: { id } }) + .tag_types() + + return (types ?? []).map((type) => type.name) + }, + }) + }, +}) + +export const TagCreateInput = inputObjectType({ + name: "TagCreateInput", + definition(t) { + t.id("id") + t.list.nonNull.field("tag_translations", { + type: "TagTranslationCreateOrUpdateInput", + }) + t.boolean("hidden", { default: false }) + t.list.nonNull.string("types") + }, +}) + +export const TagUpsertInput = inputObjectType({ + name: "TagUpsertInput", + definition(t) { + t.nonNull.id("id") + t.list.nonNull.field("tag_translations", { + type: "TagTranslationCreateOrUpdateInput", + }) + t.boolean("hidden", { default: false }) + t.list.nonNull.string("types") + }, +}) + +export const TagQueries = extendType({ + type: "Query", + definition(t) { + t.list.nonNull.field("tags", { + type: "Tag", + args: { + language: stringArg(), + search: stringArg(), + includeHidden: booleanArg(), + }, + validate: (_, { includeHidden }, ctx) => { + if (includeHidden && ctx.role !== Role.ADMIN) { + throw new ForbiddenError("admins only") + } + }, + resolve: async (_, { language, search, includeHidden }, ctx) => { + const _wrapLanguage = wrapLanguage(language) + if (search) { + return ( + await ctx.prisma.tag.findMany({ + where: { + tag_translations: { + some: { + ...(language ? { language } : {}), + OR: [ + { + name: { contains: search, mode: "insensitive" }, + }, + { + description: { contains: search, mode: "insensitive" }, + }, + ], + }, + }, + }, + }) + ).map(_wrapLanguage) + } + + const res = await ctx.prisma.tag.findMany({ + where: { + ...(!includeHidden && { + OR: [{ hidden: false }, { hidden: null }], + }), + ...(language + ? { + tag_translations: { + some: { language }, + }, + } + : {}), + }, + }) + + return res.map(_wrapLanguage) + }, + }) + }, +}) + +export const TagMutations = extendType({ + type: "Mutation", + definition(t) { + t.field("createTag", { + type: "Tag", + args: { + hidden: booleanArg(), + types: list(nonNull(stringArg())), + translations: list( + nonNull( + arg({ + type: "TagTranslationCreateOrUpdateInput", + }), + ), + ), + }, + authorize: isAdmin, + resolve: async (_, { hidden, types, translations }, ctx) => { + return ctx.prisma.tag.create({ + data: { + hidden, + ...(translations && { + tag_translations: { + create: translations, + }, + }), + ...(types && { + tag_types: { + connectOrCreate: types.map((name) => ({ + where: { + name, + }, + create: { + name, + }, + })), + }, + }), + }, + }) + }, + }) + + t.field("updateTag", { + type: "Tag", + args: { + id: nonNull(idArg()), + hidden: booleanArg(), + types: list(nonNull(stringArg())), + translations: list( + nonNull( + arg({ + type: "TagTranslationCreateOrUpdateInput", + }), + ), + ), + }, + authorize: isAdmin, + resolve: async (_, { id, hidden, types, translations }, ctx) => { + const { tag_translations, tag_types } = + (await ctx.prisma.tag.findUnique({ + where: { id }, + select: { + tag_translations: true, + tag_types: true, + }, + })) ?? {} + + const data = {} as Prisma.TagUpdateInput + + if (translations?.length) { + const translationsToCreate = translations?.filter( + (translation) => !Boolean(translation.tag_id), + ) + const translationsToUpdate = translations + ?.filter((translation) => Boolean(translation.tag_id)) + .map((translation) => ({ + where: { + tag_id: translation.tag_id ?? undefined, + language: translation.language, + }, + data: omit(translation, ["tag_id", "language"]), + })) + const translationsToDelete = tag_translations?.filter( + (translation) => + !translations.some( + (t) => + t.tag_id === translation.tag_id && + t.language === translation.language, + ), + ) + data.tag_translations = { + createMany: { data: translationsToCreate }, + updateMany: translationsToUpdate, + deleteMany: translationsToDelete, + } + } + + if (types) { + const typesToConnect = types?.filter( + (name) => !Boolean(tag_types?.find((t) => t.name === name)), + ) + const typesToDisconnect = tag_types?.filter( + (type) => !types?.some((t) => t === type.name), + ) + data.tag_types = { + connect: typesToConnect?.map((name) => ({ name })), + disconnect: typesToDisconnect, + } + } + if (!isNotNullOrUndefined(hidden)) { + data.hidden = { set: hidden } + } + + if (Object.keys(data).length === 0) { + throw new UserInputError("No data to update") + } + + return ctx.prisma.tag.update({ + where: { id }, + data, + }) + }, + }) + + t.field("deleteTag", { + type: "Tag", + args: { + id: nonNull(idArg()), + }, + authorize: isAdmin, + resolve: async (_, { id }, ctx) => { + return ctx.prisma.tag.delete({ + where: { + id, + }, + }) + }, + }) + }, +}) diff --git a/backend/graphql/TagTranslation.ts b/backend/graphql/TagTranslation.ts new file mode 100644 index 000000000..ec6d637d7 --- /dev/null +++ b/backend/graphql/TagTranslation.ts @@ -0,0 +1,103 @@ +import { + extendType, + idArg, + inputObjectType, + nonNull, + objectType, + stringArg, +} from "nexus" + +import { isAdmin } from "../accessControl" + +export const TagTranslation = objectType({ + name: "TagTranslation", + definition(t) { + t.model.tag_id() + t.model.language() + t.model.name() + t.model.description() + t.model.tag() + t.model.created_at() + t.model.updated_at() + }, +}) + +export const TagTranslationCreateOrUpdateInput = inputObjectType({ + name: "TagTranslationCreateOrUpdateInput", + definition(t) { + t.id("tag_id") + t.nonNull.string("name") + t.nonNull.string("language") + t.string("description") + }, +}) + +export const TagTranslationMutations = extendType({ + type: "Mutation", + definition(t) { + t.field("createTagTranslation", { + type: "TagTranslation", + args: { + tag_id: nonNull(idArg()), + language: nonNull(stringArg()), + name: nonNull(stringArg()), + description: stringArg(), + }, + authorize: isAdmin, + resolve: async (_, { tag_id, language, name, description }, ctx) => { + return ctx.prisma.tagTranslation.create({ + data: { + name, + language, + description, + tag: { connect: { id: tag_id } }, + }, + }) + }, + }) + + t.field("updateTagTranslation", { + type: "TagTranslation", + args: { + tag_id: nonNull(idArg()), + language: nonNull(stringArg()), + name: nonNull(stringArg()), + description: stringArg(), + }, + authorize: isAdmin, + resolve: async (_, { tag_id, language, name, description }, ctx) => { + return ctx.prisma.tagTranslation.update({ + where: { + tag_id_language: { + tag_id, + language, + }, + }, + data: { + name, + description, + }, + }) + }, + }) + + t.field("deleteTagTranslation", { + type: "TagTranslation", + args: { + tag_id: nonNull(idArg()), + language: nonNull(stringArg()), + }, + authorize: isAdmin, + resolve: async (_, { tag_id, language }, ctx) => { + return ctx.prisma.tagTranslation.delete({ + where: { + tag_id_language: { + tag_id, + language, + }, + }, + }) + }, + }) + }, +}) diff --git a/backend/graphql/TagType.ts b/backend/graphql/TagType.ts new file mode 100644 index 000000000..768e287d6 --- /dev/null +++ b/backend/graphql/TagType.ts @@ -0,0 +1,77 @@ +import { extendType, nonNull, objectType, stringArg } from "nexus" + +import { isAdmin } from "../accessControl" + +export const TagType = objectType({ + name: "TagType", + definition(t) { + t.model.name() + t.model.tags() + t.model.created_at() + t.model.updated_at() + }, +}) + +export const TagTypeQueries = extendType({ + type: "Query", + definition(t) { + t.list.nonNull.field("tagTypes", { + type: "TagType", + authorize: isAdmin, + resolve: async (_, __, ctx) => { + return ctx.prisma.tagType.findMany() + }, + }) + }, +}) + +export const TagTypeMutations = extendType({ + type: "Mutation", + definition(t) { + t.field("createTagType", { + type: "TagType", + args: { + name: nonNull(stringArg()), + }, + authorize: isAdmin, + resolve: async (_, { name }, ctx) => { + return ctx.prisma.tagType.create({ + data: { + name, + }, + }) + }, + }) + + t.field("updateTagType", { + type: "TagType", + args: { + name: nonNull(stringArg()), + }, + authorize: isAdmin, + resolve: async (_, { name }, ctx) => { + return ctx.prisma.tagType.update({ + where: { name }, + data: { + name, + }, + }) + }, + }) + + t.field("deleteTagType", { + type: "TagType", + args: { + name: nonNull(stringArg()), + }, + authorize: isAdmin, + resolve: async (_, { name }, ctx) => { + return ctx.prisma.tagType.delete({ + where: { + name, + }, + }) + }, + }) + }, +}) diff --git a/backend/graphql/User/__test__/User.test.ts b/backend/graphql/User/__test__/User.test.ts index cc45afd34..80c44f03f 100644 --- a/backend/graphql/User/__test__/User.test.ts +++ b/backend/graphql/User/__test__/User.test.ts @@ -1,7 +1,7 @@ import { gql } from "graphql-request" import { orderBy } from "lodash" -import { fakeTMCCurrent, getTestContext } from "../../../tests" +import { fakeTMCCurrent, getTestContext, ID_REGEX } from "../../../tests" import { adminUserDetails, normalUser, @@ -94,32 +94,11 @@ describe("User", () => { } `) - expect(res).toMatchInlineSnapshot( - { - currentUser: { - id: expect.any(String), - administrator: false, - email: "e@mail.com", - first_name: "first", - last_name: "last", - username: "user", - upstream_id: 1, - }, + expect(res).toMatchSnapshot({ + currentUser: { + id: expect.stringMatching(ID_REGEX), }, - ` - Object { - "currentUser": Object { - "administrator": false, - "email": "e@mail.com", - "first_name": "first", - "id": Any, - "last_name": "last", - "upstream_id": 1, - "username": "user", - }, - } - `, - ) + }) jest.clearAllMocks() }) @@ -141,16 +120,7 @@ describe("User", () => { } `) - expect(res).toMatchInlineSnapshot( - { - currentUser: null, - }, - ` - Object { - "currentUser": null, - } - `, - ) + expect(res.currentUser).toBeNull() }) }) @@ -297,14 +267,9 @@ describe("User", () => { value: true, }) - expect(res.updateResearchConsent).toMatchInlineSnapshot( - { id: expect.any(String) }, - ` - Object { - "id": Any, - } - `, - ) + expect(res.updateResearchConsent).toMatchSnapshot({ + id: expect.stringMatching(ID_REGEX), + }) const updatedConsent = await ctx.prisma.user.findFirst({ where: { upstream_id: 1 }, select: { research_consent: true }, diff --git a/backend/graphql/User/__test__/__snapshots__/User.test.ts.snap b/backend/graphql/User/__test__/__snapshots__/User.test.ts.snap index 9f15e4629..8dac21db1 100644 --- a/backend/graphql/User/__test__/__snapshots__/User.test.ts.snap +++ b/backend/graphql/User/__test__/__snapshots__/User.test.ts.snap @@ -1,8 +1,8 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`User mutations addUser creates user correctly 1`] = ` -Object { - "addUser": Object { +{ + "addUser": { "administrator": false, "email": "e@mail.com", "first_name": "first", @@ -15,15 +15,35 @@ Object { } `; +exports[`User mutations updateResearchConsent updates correctly 1`] = ` +{ + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, +} +`; + +exports[`User queries currentUser shows current user when logged in 1`] = ` +{ + "currentUser": { + "administrator": false, + "email": "e@mail.com", + "first_name": "first", + "id": StringMatching /\\[a-f\\\\d\\]\\{8\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{4\\}-\\[a-f\\\\d\\]\\{12\\}/i, + "last_name": "last", + "upstream_id": 1, + "username": "user", + }, +} +`; + exports[`User queries user_course_summary returns courses with completions 1`] = ` -Object { - "currentUser": Object { +{ + "currentUser": { "id": "20000000-0000-0000-0000-000000000102", - "user_course_summary": Array [ - Object { - "course": Object { - "exercises": Array [ - Object { + "user_course_summary": [ + { + "course": { + "exercises": [ + { "course_id": "00000000-0000-0000-0000-000000000002", "id": "50000000-0000-0000-0000-000000000003", "max_points": 3, @@ -36,12 +56,12 @@ Object { "name": "course1", }, "course_id": "00000000-0000-0000-0000-000000000002", - "exercise_completions": Array [ - Object { + "exercise_completions": [ + { "attempted": true, "completed": false, - "exercise_completion_required_actions": Array [ - Object { + "exercise_completion_required_actions": [ + { "id": "66666666-0000-0000-0000-000000000003", "value": "TOO_MANY_DUCKS", }, @@ -54,10 +74,10 @@ Object { ], "user_id": "20000000-0000-0000-0000-000000000102", }, - Object { - "course": Object { - "exercises": Array [ - Object { + { + "course": { + "exercises": [ + { "course_id": "00000000-0000-0000-0000-000000000001", "id": "50000000-0000-0000-0000-000000000001", "max_points": 2, @@ -65,7 +85,7 @@ Object { "part": 1, "section": 1, }, - Object { + { "course_id": "00000000-0000-0000-0000-000000000001", "id": "50000000-0000-0000-0000-000000000002", "max_points": 3, @@ -78,20 +98,20 @@ Object { "name": "course2", }, "course_id": "00000000-0000-0000-0000-000000000001", - "exercise_completions": Array [ - Object { + "exercise_completions": [ + { "attempted": null, "completed": true, - "exercise_completion_required_actions": Array [], + "exercise_completion_required_actions": [], "exercise_id": "50000000-0000-0000-0000-000000000001", "id": "60000000-0000-0000-0000-000000000001", "n_points": 6, "timestamp": "2000-02-01T08:00:00.000Z", }, - Object { + { "attempted": null, "completed": false, - "exercise_completion_required_actions": Array [], + "exercise_completion_required_actions": [], "exercise_id": "50000000-0000-0000-0000-000000000002", "id": "60000000-0000-0000-0000-000000000002", "n_points": 0, diff --git a/backend/graphql/User/index.ts b/backend/graphql/User/index.ts index e052193cc..06ae979b9 100644 --- a/backend/graphql/User/index.ts +++ b/backend/graphql/User/index.ts @@ -1,4 +1,4 @@ -// generated Tue Sep 27 2022 11:23:58 GMT+0300 (Itä-Euroopan kesäaika) +// generated Fri Dec 02 2022 11:28:08 GMT+0200 (Itä-Euroopan normaaliaika) export * from "./input" export * from "./model" diff --git a/backend/graphql/User/model.ts b/backend/graphql/User/model.ts index fd2af8cf6..3c34ae1b2 100644 --- a/backend/graphql/User/model.ts +++ b/backend/graphql/User/model.ts @@ -1,5 +1,5 @@ import { UserInputError } from "apollo-server-express" -import { booleanArg, idArg, nullable, objectType, stringArg } from "nexus" +import { booleanArg, idArg, objectType, stringArg } from "nexus" import { Course, Prisma } from "@prisma/client" @@ -38,7 +38,7 @@ export const User = objectType({ t.field("full_name", { type: "String", - resolve: async ({ first_name, last_name }, _, __) => { + resolve: async ({ first_name, last_name }) => { return [first_name, last_name].filter(notEmpty).join(" ") }, }) @@ -46,8 +46,8 @@ export const User = objectType({ t.list.nonNull.field("completions", { type: "Completion", args: { - course_id: nullable(stringArg()), - course_slug: nullable(stringArg()), + course_id: stringArg(), + course_slug: stringArg(), }, resolve: async (parent, args, ctx) => { const { course_id, course_slug } = args @@ -86,9 +86,9 @@ export const User = objectType({ t.list.nonNull.field("completions_registered", { type: "CompletionRegistered", args: { - course_id: nullable(stringArg()), - course_slug: nullable(stringArg()), - organization_id: nullable(stringArg()), + course_id: stringArg(), + course_slug: stringArg(), + organization_id: stringArg(), }, resolve: async (parent, args, ctx) => { const { course_id, course_slug, organization_id } = args @@ -126,14 +126,15 @@ export const User = objectType({ t.nonNull.field("project_completion", { type: "Boolean", args: { - course_id: nullable(idArg()), - course_slug: nullable(stringArg()), + course_id: idArg(), + course_slug: stringArg(), }, - resolve: async (parent, { course_id, course_slug }, ctx) => { + validate: (_, { course_id, course_slug }) => { if (!course_id && !course_slug) { - throw new Error("need course_id or course_slug") + throw new UserInputError("course_id or course_slug is required") } - + }, + resolve: async (parent, { course_id, course_slug }, ctx) => { // TODO/FIXME: Semantically it's right now, as we're quering a specific course, // be it tier or handler, and if the user does not have a project_completion // iin _that_ specific course progress, then we return false. @@ -240,7 +241,7 @@ export const User = objectType({ }) // TODO/FIXME: is this used anywhere? if is, find better name - t.nullable.field("user_course_progressess", { + t.field("user_course_progressess", { type: "UserCourseProgress", args: { course_id: idArg(), @@ -266,7 +267,7 @@ export const User = objectType({ t.list.nonNull.field("exercise_completions", { type: "ExerciseCompletion", args: { - includeDeleted: nullable(booleanArg()), + includeDeleted: booleanArg(), }, resolve: async (parent, { includeDeleted = false }, ctx) => { return ctx.prisma.user diff --git a/backend/graphql/User/queries.ts b/backend/graphql/User/queries.ts index 46cf97123..420de6f3c 100644 --- a/backend/graphql/User/queries.ts +++ b/backend/graphql/User/queries.ts @@ -11,13 +11,6 @@ export const UserQueries = extendType({ filtering: false, authorize: isAdmin, }) - /*t.list.field("users", { - type: "user", - resolve: (_, __, ctx) => { - checkAccess(ctx) - return ctx.prisma.user.findMany() - }, - })*/ t.field("user", { type: "User", @@ -27,15 +20,14 @@ export const UserQueries = extendType({ upstream_id: intArg(), }, authorize: isAdmin, - resolve: async (_, args, ctx) => { - const { id, search, upstream_id } = args - + validate: (_, { id, search, upstream_id }) => { if (!id && !search && !upstream_id) { throw new UserInputError( "must provide id, search string or upstream_id", ) } - + }, + resolve: async (_, { id, search, upstream_id }, ctx) => { const user = await ctx.prisma.user.findFirst({ where: { ...buildUserSearch(search), @@ -44,6 +36,7 @@ export const UserQueries = extendType({ }, }) if (!user) throw new UserInputError("User not found") + return user }, }) @@ -84,7 +77,7 @@ export const UserQueries = extendType({ }, }) - t.nullable.field("currentUser", { + t.field("currentUser", { type: "User", args: { search: stringArg() }, // was: email resolve: (_, __, ctx) => { diff --git a/backend/graphql/UserCourseProgress.ts b/backend/graphql/UserCourseProgress.ts index ce1288959..f385b51d1 100644 --- a/backend/graphql/UserCourseProgress.ts +++ b/backend/graphql/UserCourseProgress.ts @@ -56,7 +56,7 @@ export const UserCourseProgress = objectType({ // t.prismaFields(["*"]) - t.nullable.field("user_course_settings", { + t.field("user_course_settings", { type: "UserCourseSetting", resolve: async (parent, _, ctx) => { if (!parent.course_id) { @@ -117,6 +117,7 @@ export const UserCourseProgress = objectType({ const completedExerciseCount = exercises.filter( (e) => e.exercise_completion_id, ).length + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const totalProgress = (n_points || 0) / (max_points || 1) const exerciseProgress = completedExerciseCount / (exercises.length || 1) diff --git a/backend/graphql/UserCourseServiceProgress.ts b/backend/graphql/UserCourseServiceProgress.ts index d9116fdc2..aef1e4eb3 100644 --- a/backend/graphql/UserCourseServiceProgress.ts +++ b/backend/graphql/UserCourseServiceProgress.ts @@ -20,7 +20,7 @@ export const UserCourseServiceProgress = objectType({ t.model.course_id() t.model.course() - t.list.field("progress", { + t.nonNull.list.nonNull.field("progress", { type: "Json", resolve: async (parent, _args, ctx) => { const res = await ctx.prisma.userCourseServiceProgress.findUnique({ @@ -39,7 +39,7 @@ export const UserCourseServiceProgress = objectType({ export const UserCourseServiceProgressQueries = extendType({ type: "Query", definition(t) { - t.nullable.field("userCourseServiceProgress", { + t.field("userCourseServiceProgress", { type: "UserCourseServiceProgress", args: { user_id: idArg(), diff --git a/backend/graphql/UserCourseSettingsVisibility.ts b/backend/graphql/UserCourseSettingsVisibility.ts index 8ce7dec73..5ea5cee65 100644 --- a/backend/graphql/UserCourseSettingsVisibility.ts +++ b/backend/graphql/UserCourseSettingsVisibility.ts @@ -16,15 +16,15 @@ export const UserCourseSettingVisibilityCreateInput = inputObjectType({ name: "UserCourseSettingsVisibilityCreateInput", definition(t) { t.nonNull.string("language") - t.nullable.id("course") + t.id("course") }, }) export const UserCourseSettingVisibilityUpsertInput = inputObjectType({ name: "UserCourseSettingsVisibilityUpsertInput", definition(t) { - t.nullable.id("id") + t.id("id") t.nonNull.string("language") - t.nullable.id("course") + t.id("course") }, }) diff --git a/backend/graphql/VerifiedUser.ts b/backend/graphql/VerifiedUser.ts index 797d1cca7..dcd8a89cf 100644 --- a/backend/graphql/VerifiedUser.ts +++ b/backend/graphql/VerifiedUser.ts @@ -57,7 +57,7 @@ export const VerifiedUserMutations = extendType({ where: { id: organization_id }, }) - if (!organization || !organization?.secret_key) { + if (!organization?.secret_key) { throw new ForbiddenError("no organization or organization secret") } diff --git a/backend/graphql/index.ts b/backend/graphql/index.ts index 9e3bd7706..520f950fe 100644 --- a/backend/graphql/index.ts +++ b/backend/graphql/index.ts @@ -1,4 +1,4 @@ -// generated Tue Sep 27 2022 11:23:58 GMT+0300 (Itä-Euroopan kesäaika) +// generated Fri Dec 02 2022 11:28:08 GMT+0200 (Itä-Euroopan normaaliaika) export * from "./ABEnrollment" export * from "./ABStudy" @@ -10,6 +10,7 @@ export * from "./CourseAlias" export * from "./CourseOrganization" export * from "./CourseOwnership" export * from "./CourseStatsSubscription" +export * from "./CourseTag" export * from "./CourseTranslation" export * from "./CourseVariant" export * from "./EmailDelivery" @@ -28,6 +29,9 @@ export * from "./Service" export * from "./StoredData" export * from "./StudyModule" export * from "./StudyModuleTranslation" +export * from "./Tag" +export * from "./TagTranslation" +export * from "./TagType" export * from "./Upload" export * from "./User" export * from "./UserAppDatumConfig" diff --git a/backend/jest.config.ts b/backend/jest.config.ts index 362af39c2..2439c7adf 100644 --- a/backend/jest.config.ts +++ b/backend/jest.config.ts @@ -60,13 +60,7 @@ const config: Config = { // globalTeardown: undefined, // A set of global variables that need to be available in all test environments - globals: { - "ts-jest": { - diagnostics: { - warnOnly: true, - }, - }, - }, + // globals: undefined, // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. maxWorkers: "50%", @@ -92,7 +86,7 @@ const config: Config = { // notifyMode: "failure-change", // A preset that is used as a base for Jest's configuration - preset: "ts-jest", + // preset: "ts-jest", // Run tests from one or more projects // projects: undefined, @@ -181,8 +175,17 @@ const config: Config = { // timers: "real", // A map from regular expressions to paths to transformers - // transform: undefined, - + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + diagnostics: { + exclude: ["!**/*.(spec|test).ts"], + //warnOnly: true, + }, + }, + ], + }, // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation // transformIgnorePatterns: [ // "/node_modules/", diff --git a/backend/middlewares/validate.ts b/backend/middlewares/validate.ts new file mode 100644 index 000000000..d6abc2f65 --- /dev/null +++ b/backend/middlewares/validate.ts @@ -0,0 +1,99 @@ +import { GraphQLResolveInfo } from "graphql/type" +import { plugin } from "nexus" +import { + AllNexusNamedOutputTypeDefs, + ArgsValue, + GetGen, + MaybePromise, + printedGenTyping, + printedGenTypingImport, + SourceValue, +} from "nexus/dist/core" + +export type ValidateArgsFieldConfig< + TypeName extends string = any, + FieldName extends string = any, +> = { + type: GetGen<"allOutputTypes", string> | AllNexusNamedOutputTypeDefs + validateArgs?: ( + root: SourceValue, + args: ArgsValue, + ctx: GetGen<"context">, + info: GraphQLResolveInfo, + ) => void +} + +const ValidateArgsResolverImport = printedGenTypingImport({ + module: "middlewares/validate", + bindings: ["ValidateArgsResolver"], +}) + +const fieldDefTypes = printedGenTyping({ + optional: true, + name: "validate", + description: `Fork of validateArgs from connectionPlugin.`, + type: "ValidateArgsResolver", + imports: [ValidateArgsResolverImport], +}) + +export type ValidateArgsResolver< + TypeName extends string, + FieldName extends string, +> = ( + root: SourceValue, + args: ArgsValue, + context: GetGen<"context">, + info: GraphQLResolveInfo, +) => MaybePromise + +export const validateArgsPlugin = () => { + const ensureError = + ( + _root: any, + _args: any, + _ctx: GetGen<"context">, + _info: GraphQLResolveInfo, + ) => + (error: Error) => { + if (error instanceof Error) { + throw error + } + throw new Error("Invalid arguments") + } + + return plugin({ + name: "validateArgPlugin", + fieldDefTypes, + onCreateFieldResolver(config) { + const validate = config.fieldConfig.extensions?.nexus?.config + ?.validate as ValidateArgsResolver + + if (!validate) { + return + } + if (typeof validate !== "function") { + console.error(new Error("validateArgs must be a function")) + return + } + + return function (root, args, ctx, info, next) { + let toComplete + try { + toComplete = validate(root, args, ctx, info) + } catch (e) { + toComplete = Promise.reject(e) + } + + return plugin.completeValue( + toComplete, + () => { + return next(root, args, ctx, info) + }, + (err) => { + ensureError(root, args, ctx, info)(err) + }, + ) + } + }, + }) +} diff --git a/backend/migrations/20220427094330_create-tables-tag-tag-translation-course-tag.ts b/backend/migrations/20220427094330_create-tables-tag-tag-translation-course-tag.ts new file mode 100644 index 000000000..f6849c0e0 --- /dev/null +++ b/backend/migrations/20220427094330_create-tables-tag-tag-translation-course-tag.ts @@ -0,0 +1,112 @@ +import { Knex } from "knex" + +import { EXTENSION_PATH } from "../config" +import { createExtensions } from "../util/db-functions" + +export async function up(knex: Knex): Promise { + await createExtensions(knex) + + await knex.raw(` + CREATE TABLE IF NOT EXISTS "tag" ( + "id" uuid NOT NULL DEFAULT ${EXTENSION_PATH}.uuid_generate_v4(), + "hidden" boolean NOT NULL DEFAULT false, + "created_at" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + `) + + await knex.raw(` + CREATE TABLE IF NOT EXISTS "tag_translation" ( + "tag_id" uuid NOT NULL, + "language" text NOT NULL, + "name" text NOT NULL, + "description" text, + "created_at" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + `) + + await knex.raw(` + CREATE TABLE IF NOT EXISTS "course_tag" ( + "course_id" uuid NOT NULL, + "tag_id" uuid NOT NULL, + "created_at" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + `) + + await knex.raw(` + CREATE TABLE IF NOT EXISTS "tag_type" ( + "name" text NOT NULL, + "created_at" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) WITHOUT TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP + ); + `) + + await knex.raw(` + ALTER TABLE "tag" + ADD CONSTRAINT tag_pkey PRIMARY KEY ("id"); + `) + + await knex.raw(` + ALTER TABLE "tag_translation" + ADD CONSTRAINT tag_translation_pkey PRIMARY KEY ("tag_id", "language"); + ALTER TABLE "tag_translation" + ADD CONSTRAINT tag_translation_tag_fkey FOREIGN KEY ("tag_id") REFERENCES "tag"("id") ON DELETE CASCADE; + `) + + await knex.raw(` + ALTER TABLE "course_tag" + ADD CONSTRAINT course_tag_pkey PRIMARY KEY ("course_id", "tag_id"); + ALTER TABLE "course_tag" + ADD CONSTRAINT course_tag_course_fkey FOREIGN KEY ("course_id") REFERENCES "course"("id") ON DELETE CASCADE; + ALTER TABLE "course_tag" + ADD CONSTRAINT course_tag_tag_fkey FOREIGN KEY ("tag_id") REFERENCES "tag"("id") ON DELETE CASCADE; + `) + + await knex.raw(` + ALTER TABLE "tag_type" + ADD CONSTRAINT tag_type_pkey PRIMARY KEY ("name"); + `) + + await knex.raw(` + CREATE TABLE IF NOT EXISTS "_TagToTagType" ( + "A" uuid NOT NULL, + "B" text NOT NULL + ); + `) + + await knex.raw(` + CREATE UNIQUE INDEX IF NOT EXISTS "_TagToTagType_AB_unique" ON "_TagToTagType" USING btree ("A", "B"); + `) + + await knex.raw(` + ALTER TABLE ONLY "_TagToTagType" + ADD CONSTRAINT "_TagToTagType_A_fkey" FOREIGN KEY ("A") REFERENCES "tag"("id") ON DELETE CASCADE; + ALTER TABLE ONLY "_TagToTagType" + ADD CONSTRAINT "_TagToTagType_B_fkey" FOREIGN KEY ("B") REFERENCES "tag_type"("name") ON DELETE CASCADE; + `) + + await knex.raw(` + CREATE UNIQUE INDEX IF NOT EXISTS "tag_translation.name_language._UNIQUE" + ON "tag_translation" ("name", "language"); + `) +} + +export async function down(knex: Knex): Promise { + await knex.raw(` + DROP TABLE IF EXISTS "_TagToTagType"; + `) + await knex.raw(` + DROP TABLE IF EXISTS "tag_type"; + `) + await knex.raw(` + DROP TABLE IF EXISTS "course_tag"; + `) + await knex.raw(` + DROP TABLE IF EXISTS "tag_translation"; + `) + await knex.raw(` + DROP TABLE IF EXISTS "tag"; + `) +} diff --git a/backend/package-lock.json b/backend/package-lock.json index 58f42d806..b3629ca08 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -12,6 +12,7 @@ "dependencies": { "@devoxa/prisma-relay-cursor-connection": "^2.2.1", "@google-cloud/storage": "^5.19.1", + "@ianvs/prettier-plugin-sort-imports": "^3.7.1", "@prisma/client": "2.23", "@sentry/integrations": "^6.19.6", "@sentry/node": "^6.19.6", @@ -62,7 +63,7 @@ "@types/express": "^4.17.12", "@types/faker": "^5.5.9", "@types/graphql-upload": "^8.0.12", - "@types/jest": "^28.1.2", + "@types/jest": "^29.2.4", "@types/lodash": "^4.14.190", "@types/luxon": "^3.1.0", "@types/mime-types": "^2.1.1", @@ -76,23 +77,23 @@ "get-port": "^5.0.0", "graceful-fs": "^4.2.10", "graphql-request": "^4.3.0", - "jest": "^28.1.1", + "jest": "^29.3.1", "jest-junit": "^13.2.0", "jest-mock": "^28.1.1", "locate-path": "^7.1.1", "nanoid": "^3.3.2", "nock": "^13.2.7", - "ts-jest": "^28.0.5", + "prettier": "^2.8.0", + "ts-jest": "^29.0.3", "ts-node": "^10.8.1", "ts-node-dev": "^2.0.0", - "typescript": "^4.7.4" + "typescript": "^4.9.4" } }, "node_modules/@ampproject/remapping": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.0.tgz", "integrity": "sha512-d5RysTlJ7hmw5Tw4UxgxcY3lkMe92n8sXCcuLPAyIAHK6j8DefDwtGnVVDgOnv+RnEosulDJ9NPKQL27bDId0g==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.0" }, @@ -253,7 +254,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, "dependencies": { "@babel/highlight": "^7.16.7" }, @@ -265,7 +265,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -274,7 +273,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -304,7 +302,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -313,7 +310,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", - "dev": true, "dependencies": { "@babel/types": "^7.18.2", "@jridgewell/gen-mapping": "^0.3.0", @@ -352,7 +348,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.17.10", "@babel/helper-validator-option": "^7.16.7", @@ -370,7 +365,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -444,7 +438,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -465,7 +458,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, "dependencies": { "@babel/template": "^7.16.7", "@babel/types": "^7.17.0" @@ -478,7 +470,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -502,7 +493,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -514,7 +504,6 @@ "version": "7.18.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -542,9 +531,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", - "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -584,7 +573,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", - "dev": true, "dependencies": { "@babel/types": "^7.18.2" }, @@ -608,7 +596,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -620,7 +607,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -629,7 +615,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -653,7 +638,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", - "dev": true, "dependencies": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.18.2", @@ -667,7 +651,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", @@ -681,7 +664,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -693,7 +675,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -707,7 +688,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -716,7 +696,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, "engines": { "node": ">=4" } @@ -725,7 +704,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -737,7 +715,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -1139,6 +1116,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", @@ -1932,7 +1924,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", @@ -1946,7 +1937,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.18.2", @@ -1967,7 +1957,6 @@ "version": "7.18.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" @@ -2188,6 +2177,30 @@ "node": ">=6" } }, + "node_modules/@ianvs/prettier-plugin-sort-imports": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-3.7.1.tgz", + "integrity": "sha512-XDnBUUruJY9KgNd7T2ZHnVPWo5B9NzVDCLEMm7HjXTA3rTtMg5Q46gYRjLvampDXSmN8+icu54aRE3IIT8U+1w==", + "dependencies": { + "@babel/core": "^7.17.7", + "@babel/generator": "^7.17.7", + "@babel/parser": "^7.17.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", + "javascript-natural-sort": "0.7.1", + "lodash.clone": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "peerDependencies": { + "@vue/compiler-sfc": ">=3.0.0", + "prettier": "2.x" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + } + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2214,60 +2227,59 @@ } }, "node_modules/@jest/console": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.1.tgz", - "integrity": "sha512-0RiUocPVFEm3WRMOStIHbRWllG6iW6E3/gUPnf4lkrVFyXIIDeCe+vlKeYyFOMhB2EPE6FLFCNADSOOQMaqvyA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz", + "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==", "dev": true, "dependencies": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^28.1.1", - "jest-util": "^28.1.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.1.tgz", - "integrity": "sha512-3pYsBoZZ42tXMdlcFeCc/0j9kOlK7MYuXs2B1QbvDgMoW1K9NJ4G/VYvIbMb26iqlkTfPHo7SC2JgjDOk/mxXw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz", + "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==", "dev": true, "dependencies": { - "@jest/console": "^28.1.1", - "@jest/reporters": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/console": "^29.3.1", + "@jest/reporters": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^28.0.2", - "jest-config": "^28.1.1", - "jest-haste-map": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.1", - "jest-resolve-dependencies": "^28.1.1", - "jest-runner": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-snapshot": "^28.1.1", - "jest-util": "^28.1.1", - "jest-validate": "^28.1.1", - "jest-watcher": "^28.1.1", + "jest-changed-files": "^29.2.0", + "jest-config": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-resolve-dependencies": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", + "jest-watcher": "^29.3.1", "micromatch": "^4.0.4", - "pretty-format": "^28.1.1", - "rimraf": "^3.0.0", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -2278,104 +2290,132 @@ } } }, - "node_modules/@jest/core/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/@jest/environment": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", + "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", "dev": true, "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-mock": "^29.3.1" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/environment": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.1.tgz", - "integrity": "sha512-9auVQ2GzQ7nrU+lAr8KyY838YahElTX9HVjbQPPS2XjlxQ+na18G113OoBhyBGBtD6ZnO/SrUy5WR8EzOj1/Uw==", + "node_modules/@jest/environment/node_modules/jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", "dev": true, "dependencies": { - "@jest/fake-timers": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-mock": "^28.1.1" + "jest-util": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.1.tgz", - "integrity": "sha512-/+tQprrFoT6lfkMj4mW/mUIfAmmk/+iQPmg7mLDIFOf2lyf7EBHaS+x3RbeR0VZVMe55IvX7QRoT/2aK3AuUXg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", + "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", "dev": true, "dependencies": { - "expect": "^28.1.1", - "jest-snapshot": "^28.1.1" + "expect": "^29.3.1", + "jest-snapshot": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.1.tgz", - "integrity": "sha512-n/ghlvdhCdMI/hTcnn4qV57kQuV9OTsZzH1TTCVARANKhl6hXJqLKUkwX69ftMGpsbpt96SsDD8n8LD2d9+FRw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", + "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", "dev": true, "dependencies": { - "jest-get-type": "^28.0.2" + "jest-get-type": "^29.2.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.1.tgz", - "integrity": "sha512-BY/3+TyLs5+q87rGWrGUY5f8e8uC3LsVHS9Diz8+FV3ARXL4sNnkLlIB8dvDvRrp+LUCGM+DLqlsYubizGUjIA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", + "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", "dev": true, "dependencies": { - "@jest/types": "^28.1.1", - "@sinonjs/fake-timers": "^9.1.1", + "@jest/types": "^29.3.1", + "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", - "jest-message-util": "^28.1.1", - "jest-mock": "^28.1.1", - "jest-util": "^28.1.1" + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.1.tgz", - "integrity": "sha512-dEgl/6v7ToB4vXItdvcltJBgny0xBE6xy6IYQrPJAJggdEinGxCDMivNv7sFzPcTITGquXD6UJwYxfJ/5ZwDSg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", + "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.1", - "@jest/expect": "^28.1.1", - "@jest/types": "^28.1.1" + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/types": "^29.3.1", + "jest-mock": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals/node_modules/jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.1.tgz", - "integrity": "sha512-597Zj4D4d88sZrzM4atEGLuO7SdA/YrOv9SRXHXRNC+/FwPCWxZhBAEzhXoiJzfRwn8zes/EjS8Lo6DouGN5Gg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz", + "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", - "@jridgewell/trace-mapping": "^0.3.7", + "@jest/console": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", + "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -2387,17 +2427,16 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^28.1.1", - "jest-util": "^28.1.1", - "jest-worker": "^28.1.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.0" + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -2409,107 +2448,113 @@ } }, "node_modules/@jest/schemas": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.0.2.tgz", - "integrity": "sha512-YVDJZjd4izeTDkij00vHHAymNXQ6WWsdChFRK86qck6Jpr3DCL5W3Is3vslviRlP+bLuMYRLbdp98amMvqudhA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", + "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.23.3" + "@sinclair/typebox": "^0.24.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.0.2.tgz", - "integrity": "sha512-Y9dxC8ZpN3kImkk0LkK5XCEneYMAXlZ8m5bflmSL5vrwyeUpJfentacCUg6fOb8NOpOO7hz2+l37MV77T6BFPw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", + "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.1.tgz", - "integrity": "sha512-hPmkugBktqL6rRzwWAtp1JtYT4VHwv8OQ+9lE5Gymj6dHzubI/oJHMUpPOt8NrdVWSrz9S7bHjJUmv2ggFoUNQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz", + "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==", "dev": true, "dependencies": { - "@jest/console": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/console": "^29.3.1", + "@jest/types": "^29.3.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.1.tgz", - "integrity": "sha512-nuL+dNSVMcWB7OOtgb0EGH5AjO4UBCt68SLP08rwmC+iRhyuJWS9MtZ/MpipxFwKAlHFftbMsydXqWre8B0+XA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz", + "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==", "dev": true, "dependencies": { - "@jest/test-result": "^28.1.1", + "@jest/test-result": "^29.3.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.1", + "jest-haste-map": "^29.3.1", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.1.tgz", - "integrity": "sha512-PkfaTUuvjUarl1EDr5ZQcCA++oXkFCP9QFUkG0yVKVmNObjhrqDy0kbMpMebfHWm3CCDHjYNem9eUSH8suVNHQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", + "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^28.1.1", - "@jridgewell/trace-mapping": "^0.3.7", + "@jest/types": "^29.3.1", + "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.1", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.1", + "jest-haste-map": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/@jest/transform/node_modules/write-file-atomic": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", - "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/@jest/types": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.1.tgz", - "integrity": "sha512-vRXVqSg1VhDnB8bWcmvLzmg0Bt9CRKVgHPXqYwvWMX3TvAjeO+nRuK6+VdTKCtWOvYlmkF/HqNAL/z+N3B53Kw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", + "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -2517,7 +2562,7 @@ "chalk": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@josephg/resolvable": { @@ -2529,7 +2574,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -2540,10 +2584,9 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.4.tgz", - "integrity": "sha512-cz8HFjOFfUBtvN+NXYSFMHYRdxZMaEl0XypVrhzxBgadKIXhIkRd8aMeHhmF56Sl7SuS8OnUpQ73/k9LE4VnLg==", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "engines": { "node": ">=6.0.0" } @@ -2552,25 +2595,22 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", - "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.10.tgz", - "integrity": "sha512-Ht8wIW5v165atIX1p+JvKR5ONzUyF4Ac8DZIQ5kZs9zrb6M8SJNXpx1zn04rn65VjBMygRoMXcyYwNK0fT7bEg==", - "dev": true + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", - "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", - "dev": true, + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, "node_modules/@newrelic/aws-sdk": { @@ -2901,15 +2941,15 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sinclair/typebox": { - "version": "0.23.5", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz", - "integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==", + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", "dev": true }, "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "dependencies": { "type-detect": "4.0.8" @@ -2957,9 +2997,9 @@ } }, "node_modules/@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", + "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -2989,9 +3029,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.17.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", - "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", + "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dev": true, "dependencies": { "@babel/types": "^7.3.0" @@ -3140,13 +3180,13 @@ } }, "node_modules/@types/jest": { - "version": "28.1.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-28.1.2.tgz", - "integrity": "sha512-5dNM7mMuIrCtNJsFfvUO/5xCrG8swuT2c7ND+sl3XwlwxJf3k7e7o+PRvcFN/iIm8XhCqHqxLOj9yutDDOJoRg==", + "version": "29.2.4", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.4.tgz", + "integrity": "sha512-PipFB04k2qTRPePduVLTRiPzQfvMeLwUN3Z21hsAKaB/W9IIzgB2pizCL466ftJlcyZqnHoC9ZHpxLGl3fS86A==", "dev": true, "dependencies": { - "jest-matcher-utils": "^28.0.0", - "pretty-format": "^28.0.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "node_modules/@types/keygrip": { @@ -3231,9 +3271,9 @@ } }, "node_modules/@types/prettier": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", - "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", "dev": true }, "node_modules/@types/qs": { @@ -3634,21 +3674,21 @@ } }, "node_modules/babel-jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.1.tgz", - "integrity": "sha512-MEt0263viUdAkTq5D7upHPNxvt4n9uLUGa6pPz3WviNBMtOmStb1lIXS3QobnoqM+qnH+vr4EKlvhe8QcmxIYw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", + "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", "dev": true, "dependencies": { - "@jest/transform": "^28.1.1", + "@jest/transform": "^29.3.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^28.1.1", + "babel-preset-jest": "^29.2.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" @@ -3680,9 +3720,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.1.tgz", - "integrity": "sha512-NovGCy5Hn25uMJSAU8FaHqzs13cFoOI4lhIujiepssjCKRsAo3TA734RDWSGxuFTsUJXerYOqQQodlxgmtqbzw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz", + "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -3691,7 +3731,7 @@ "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/babel-plugin-polyfill-corejs2": { @@ -3766,16 +3806,16 @@ } }, "node_modules/babel-preset-jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.1.tgz", - "integrity": "sha512-FCq9Oud0ReTeWtcneYf/48981aTfXYuB9gbU4rBNNJVBSQ6ssv7E6v/qvbBxtOWwZFXjLZwpg+W3q7J6vhH25g==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz", + "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^28.1.1", + "babel-plugin-jest-hoist": "^29.2.0", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -3930,7 +3970,6 @@ "version": "4.20.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -4079,7 +4118,6 @@ "version": "1.0.30001358", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001358.tgz", "integrity": "sha512-hvp8PSRymk85R20bsDra7ZTCpSVGN/PAz9pSAjPSjKC+rNmnUk5vCRgJwiTT/O4feQ/yu/drvZYpKxxhbFuChw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -4153,10 +4191,13 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "node_modules/ci-info": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", - "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", - "dev": true + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", + "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/cjs-module-lexer": { "version": "1.2.2", @@ -4460,7 +4501,6 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, "dependencies": { "safe-buffer": "~5.1.1" } @@ -4733,12 +4773,12 @@ } }, "node_modules/diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", + "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/dot-prop": { @@ -4804,13 +4844,12 @@ "node_modules/electron-to-chromium": { "version": "1.4.164", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.164.tgz", - "integrity": "sha512-K7iy5y6XyP9Pzh3uaDti0KC4JUNT6T1tLG5RTOmesqq2YgAJpYYYJ32m+anvZYjCV35llPTEh87kvEV/uSsiyQ==", - "dev": true + "integrity": "sha512-K7iy5y6XyP9Pzh3uaDti0KC4JUNT6T1tLG5RTOmesqq2YgAJpYYYJ32m+anvZYjCV35llPTEh87kvEV/uSsiyQ==" }, "node_modules/emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "engines": { "node": ">=12" @@ -4915,7 +4954,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -5007,19 +5045,19 @@ } }, "node_modules/expect": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.1.tgz", - "integrity": "sha512-/AANEwGL0tWBwzLNOvO0yUdy2D52jVdNXppOqswC49sxMN2cPWsGCQdzuIf9tj6hHoBQzNvx75JUYuQAckPo3w==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", + "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", "dev": true, "dependencies": { - "@jest/expect-utils": "^28.1.1", - "jest-get-type": "^28.0.2", - "jest-matcher-utils": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-util": "^28.1.1" + "@jest/expect-utils": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/express": { @@ -5166,9 +5204,9 @@ "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" }, "node_modules/fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "dependencies": { "bser": "2.1.1" @@ -5421,7 +5459,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -5523,7 +5560,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -6031,9 +6067,9 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", - "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { "@babel/core": "^7.12.3", @@ -6096,9 +6132,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -6108,22 +6144,27 @@ "node": ">=8" } }, + "node_modules/javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, "node_modules/jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.1.tgz", - "integrity": "sha512-qw9YHBnjt6TCbIDMPMpJZqf9E12rh6869iZaN08/vpOGgHJSAaLLUn6H8W3IAEuy34Ls3rct064mZLETkxJ2XA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", + "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", "dev": true, "dependencies": { - "@jest/core": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/core": "^29.3.1", + "@jest/types": "^29.3.1", "import-local": "^3.0.2", - "jest-cli": "^28.1.1" + "jest-cli": "^29.3.1" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -6135,64 +6176,64 @@ } }, "node_modules/jest-changed-files": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.0.2.tgz", - "integrity": "sha512-QX9u+5I2s54ZnGoMEjiM2WeBvJR2J7w/8ZUmH2um/WLAuGAYFQcsVXY9+1YL6k0H/AGUdH8pXUAv6erDqEsvIA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz", + "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==", "dev": true, "dependencies": { "execa": "^5.0.0", - "throat": "^6.0.1" + "p-limit": "^3.1.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-circus": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.1.tgz", - "integrity": "sha512-75+BBVTsL4+p2w198DQpCeyh1RdaS2lhEG87HkaFX/UG0gJExVq2skG2pT7XZEGBubNj2CytcWSPan4QEPNosw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz", + "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.1", - "@jest/expect": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^28.1.1", - "jest-matcher-utils": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-snapshot": "^28.1.1", - "jest-util": "^28.1.1", - "pretty-format": "^28.1.1", + "jest-each": "^29.3.1", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", + "p-limit": "^3.1.0", + "pretty-format": "^29.3.1", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-cli": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.1.tgz", - "integrity": "sha512-+sUfVbJqb1OjBZ0OdBbI6OWfYM1i7bSfzYy6gze1F1w3OKWq8ZTEKkZ8a7ZQPq6G/G1qMh/uKqpdWhgl11NFQQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz", + "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==", "dev": true, "dependencies": { - "@jest/core": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/core": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^28.1.1", - "jest-util": "^28.1.1", - "jest-validate": "^28.1.1", + "jest-config": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -6200,7 +6241,7 @@ "jest": "bin/jest.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -6211,64 +6252,78 @@ } } }, + "node_modules/jest-cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/jest-cli/node_modules/yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" } }, "node_modules/jest-cli/node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "engines": { "node": ">=12" } }, "node_modules/jest-config": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.1.tgz", - "integrity": "sha512-tASynMhS+jVV85zKvjfbJ8nUyJS/jUSYZ5KQxLUN2ZCvcQc/OmhQl2j6VEL3ezQkNofxn5pQ3SPYWPHb0unTZA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", + "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^28.1.1", - "@jest/types": "^28.1.1", - "babel-jest": "^28.1.1", + "@jest/test-sequencer": "^29.3.1", + "@jest/types": "^29.3.1", + "babel-jest": "^29.3.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^28.1.1", - "jest-environment-node": "^28.1.1", - "jest-get-type": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.1", - "jest-runner": "^28.1.1", - "jest-util": "^28.1.1", - "jest-validate": "^28.1.1", + "jest-circus": "^29.3.1", + "jest-environment-node": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^28.1.1", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@types/node": "*", @@ -6296,94 +6351,108 @@ } }, "node_modules/jest-diff": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.1.tgz", - "integrity": "sha512-/MUUxeR2fHbqHoMMiffe/Afm+U8U4olFRJ0hiVG2lZatPJcnGxx292ustVu7bULhjV65IYMxRdploAKLbcrsyg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", + "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.1" + "diff-sequences": "^29.3.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", - "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", + "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.1.tgz", - "integrity": "sha512-A042rqh17ZvEhRceDMi784ppoXR7MWGDEKTXEZXb4svt0eShMZvijGxzKsx+yIjeE8QYmHPrnHiTSQVhN4nqaw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz", + "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==", "dev": true, "dependencies": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "jest-util": "^28.1.1", - "pretty-format": "^28.1.1" + "jest-get-type": "^29.2.0", + "jest-util": "^29.3.1", + "pretty-format": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.1.tgz", - "integrity": "sha512-2aV/eeY/WNgUUJrrkDJ3cFEigjC5fqT1+fCclrY6paqJ5zVPoM//sHmfgUUp7WLYxIdbPwMiVIzejpN56MxnNA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz", + "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==", "dev": true, "dependencies": { - "@jest/environment": "^28.1.1", - "@jest/fake-timers": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-mock": "^28.1.1", - "jest-util": "^28.1.1" + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", + "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.1.tgz", - "integrity": "sha512-ZrRSE2o3Ezh7sb1KmeLEZRZ4mgufbrMwolcFHNRSjKZhpLa8TdooXOOFlSwoUzlbVs1t0l7upVRW2K7RWGHzbQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", + "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", "dev": true, "dependencies": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.1", - "jest-worker": "^28.1.1", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", "micromatch": "^4.0.4", "walker": "^1.0.8" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" @@ -6405,51 +6474,51 @@ } }, "node_modules/jest-leak-detector": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.1.tgz", - "integrity": "sha512-4jvs8V8kLbAaotE+wFR7vfUGf603cwYtFf1/PYEsyX2BAjSzj8hQSVTP6OWzseTl0xL6dyHuKs2JAks7Pfubmw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz", + "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==", "dev": true, "dependencies": { - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.1" + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.1.tgz", - "integrity": "sha512-NPJPRWrbmR2nAJ+1nmnfcKKzSwgfaciCCrYZzVnNoxVoyusYWIjkBMNvu0RHJe7dNj4hH3uZOPZsQA+xAYWqsw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", + "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.1" + "jest-diff": "^29.3.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.1.tgz", - "integrity": "sha512-xoDOOT66fLfmTRiqkoLIU7v42mal/SqwDKvfmfiWAdJMSJiU+ozgluO7KbvoAgiwIrrGZsV7viETjc8GNrA/IQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", + "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^28.1.1", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-mock": { @@ -6465,10 +6534,39 @@ "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" } }, + "node_modules/jest-mock/node_modules/@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.24.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/jest-mock/node_modules/@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "engines": { "node": ">=6" @@ -6483,150 +6581,165 @@ } }, "node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", + "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.1.tgz", - "integrity": "sha512-/d1UbyUkf9nvsgdBildLe6LAD4DalgkgZcKd0nZ8XUGPyA/7fsnaQIlKVnDiuUXv/IeZhPEDrRJubVSulxrShA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz", + "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.1", + "jest-haste-map": "^29.3.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.1.1", - "jest-validate": "^28.1.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve-dependencies": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.1.tgz", - "integrity": "sha512-p8Y150xYJth4EXhOuB8FzmS9r8IGLEioiaetgdNGb9VHka4fl0zqWlVe4v7mSkYOuEUg2uB61iE+zySDgrOmgQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz", + "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==", "dev": true, "dependencies": { - "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.1.1" + "jest-regex-util": "^29.2.0", + "jest-snapshot": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.1.tgz", - "integrity": "sha512-W5oFUiDBgTsCloTAj6q95wEvYDB0pxIhY6bc5F26OucnwBN+K58xGTGbliSMI4ChQal5eANDF+xvELaYkJxTmA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz", + "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==", "dev": true, "dependencies": { - "@jest/console": "^28.1.1", - "@jest/environment": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/console": "^29.3.1", + "@jest/environment": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.10.2", + "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^28.1.1", - "jest-environment-node": "^28.1.1", - "jest-haste-map": "^28.1.1", - "jest-leak-detector": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-resolve": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-util": "^28.1.1", - "jest-watcher": "^28.1.1", - "jest-worker": "^28.1.1", - "source-map-support": "0.5.13", - "throat": "^6.0.1" + "jest-docblock": "^29.2.0", + "jest-environment-node": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-leak-detector": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-resolve": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-util": "^29.3.1", + "jest-watcher": "^29.3.1", + "jest-worker": "^29.3.1", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runtime": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.1.tgz", - "integrity": "sha512-J89qEJWW0leOsqyi0D9zHpFEYHwwafFdS9xgvhFHtIdRghbadodI0eA+DrthK/1PebBv3Px8mFSMGKrtaVnleg==", - "dev": true, - "dependencies": { - "@jest/environment": "^28.1.1", - "@jest/fake-timers": "^28.1.1", - "@jest/globals": "^28.1.1", - "@jest/source-map": "^28.0.2", - "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz", + "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/globals": "^29.3.1", + "@jest/source-map": "^29.2.0", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", + "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-mock": "^28.1.1", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.1", - "jest-snapshot": "^28.1.1", - "jest-util": "^28.1.1", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.1.tgz", - "integrity": "sha512-1KjqHJ98adRcbIdMizjF5DipwZFbvxym/kFO4g4fVZCZRxH/dqV8TiBFCa6rqic3p0karsy8RWS1y4E07b7P0A==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", + "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/expect-utils": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^28.1.1", + "expect": "^29.3.1", "graceful-fs": "^4.2.9", - "jest-diff": "^28.1.1", - "jest-get-type": "^28.0.2", - "jest-haste-map": "^28.1.1", - "jest-matcher-utils": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-util": "^28.1.1", + "jest-diff": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-haste-map": "^29.3.1", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", "natural-compare": "^1.4.0", - "pretty-format": "^28.1.1", + "pretty-format": "^29.3.1", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -6639,12 +6752,12 @@ } }, "node_modules/jest-util": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.1.tgz", - "integrity": "sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", + "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", "dev": true, "dependencies": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -6652,24 +6765,24 @@ "picomatch": "^2.2.3" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.1.tgz", - "integrity": "sha512-Kpf6gcClqFCIZ4ti5++XemYJWUPCFUW+N2gknn+KgnDf549iLul3cBuKVe1YcWRlaF8tZV8eJCap0eECOEE3Ug==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz", + "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==", "dev": true, "dependencies": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.2.0", "leven": "^3.1.0", - "pretty-format": "^28.1.1" + "pretty-format": "^29.3.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate/node_modules/camelcase": { @@ -6685,43 +6798,43 @@ } }, "node_modules/jest-watcher": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.1.tgz", - "integrity": "sha512-RQIpeZ8EIJMxbQrXpJQYIIlubBnB9imEHsxxE41f54ZwcqWLysL/A0ZcdMirf+XsMn3xfphVQVV4EW0/p7i7Ug==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz", + "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==", "dev": true, "dependencies": { - "@jest/test-result": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.1", + "emittery": "^0.13.1", + "jest-util": "^29.3.1", "string-length": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.1.tgz", - "integrity": "sha512-Au7slXB08C6h+xbJPp7VIb6U0XX5Kc9uel/WFc6/rcTzGiaVCBRngBExSYuXSLFPULPSYU3cJ3ybS988lNFQhQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", + "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.3.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "3.14.1", @@ -6740,7 +6853,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" }, @@ -6771,7 +6883,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -7004,16 +7115,26 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" }, + "node_modules/lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, "node_modules/lodash.sortby": { @@ -7542,8 +7663,7 @@ "node_modules/node-releases": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", - "dev": true + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" }, "node_modules/nodemailer": { "version": "6.7.5", @@ -8001,8 +8121,7 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -8104,19 +8223,32 @@ "node": ">=10" } }, + "node_modules/prettier": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz", + "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.1.tgz", - "integrity": "sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/pretty-format/node_modules/ansi-styles": { @@ -8835,9 +8967,9 @@ } }, "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" @@ -8974,31 +9106,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -9069,22 +9176,6 @@ "node": ">= 6" } }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -9104,12 +9195,6 @@ "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, - "node_modules/throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -9144,7 +9229,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, "engines": { "node": ">=4" } @@ -9187,14 +9271,14 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "node_modules/ts-jest": { - "version": "28.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.5.tgz", - "integrity": "sha512-Sx9FyP9pCY7pUzQpy4FgRZf2bhHY3za576HMKJFs+OnQ9jS96Du5vNsDKkyedQkik+sEabbKAnCliv9BEsHZgQ==", + "version": "29.0.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", + "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==", "dev": true, "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", - "jest-util": "^28.0.0", + "jest-util": "^29.0.0", "json5": "^2.2.1", "lodash.memoize": "4.x", "make-error": "1.x", @@ -9205,18 +9289,22 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "babel-jest": "^28.0.0", - "jest": "^28.0.0", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", "typescript": ">=4.3" }, "peerDependenciesMeta": { "@babel/core": { "optional": true }, + "@jest/types": { + "optional": true + }, "babel-jest": { "optional": true }, @@ -9226,9 +9314,9 @@ } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -9241,9 +9329,9 @@ } }, "node_modules/ts-jest/node_modules/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "engines": { "node": ">=12" @@ -9424,9 +9512,9 @@ } }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -9838,7 +9926,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.0.tgz", "integrity": "sha512-d5RysTlJ7hmw5Tw4UxgxcY3lkMe92n8sXCcuLPAyIAHK6j8DefDwtGnVVDgOnv+RnEosulDJ9NPKQL27bDId0g==", - "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.0" } @@ -9954,7 +10041,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, "requires": { "@babel/highlight": "^7.16.7" } @@ -9962,14 +10048,12 @@ "@babel/compat-data": { "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", - "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", - "dev": true + "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==" }, "@babel/core": { "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", - "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -9990,9 +10074,8 @@ "dependencies": { "semver": { "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -10000,7 +10083,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", - "dev": true, "requires": { "@babel/types": "^7.18.2", "@jridgewell/gen-mapping": "^0.3.0", @@ -10030,7 +10112,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", - "dev": true, "requires": { "@babel/compat-data": "^7.17.10", "@babel/helper-validator-option": "^7.16.7", @@ -10041,8 +10122,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -10098,8 +10178,7 @@ "@babel/helper-environment-visitor": { "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", - "dev": true + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==" }, "@babel/helper-explode-assignable-expression": { "version": "7.16.7", @@ -10114,7 +10193,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/types": "^7.17.0" @@ -10124,7 +10202,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -10142,7 +10219,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -10151,7 +10227,6 @@ "version": "7.18.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", - "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -10173,9 +10248,9 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.17.12", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", - "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true }, "@babel/helper-remap-async-to-generator": { @@ -10206,7 +10281,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", - "dev": true, "requires": { "@babel/types": "^7.18.2" } @@ -10224,7 +10298,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -10232,14 +10305,12 @@ "@babel/helper-validator-identifier": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" }, "@babel/helper-validator-option": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" }, "@babel/helper-wrap-function": { "version": "7.16.8", @@ -10257,7 +10328,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.18.2", @@ -10268,7 +10338,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", @@ -10279,7 +10348,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -10288,7 +10356,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -10299,7 +10366,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -10307,14 +10373,12 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -10324,8 +10388,7 @@ "@babel/parser": { "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", - "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", - "dev": true + "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.17.12", @@ -10586,6 +10649,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, "@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", @@ -11128,7 +11200,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", @@ -11139,7 +11210,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.18.2", @@ -11157,7 +11227,6 @@ "version": "7.18.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" @@ -11331,6 +11400,21 @@ "yargs": "^16.2.0" } }, + "@ianvs/prettier-plugin-sort-imports": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-3.7.1.tgz", + "integrity": "sha512-XDnBUUruJY9KgNd7T2ZHnVPWo5B9NzVDCLEMm7HjXTA3rTtMg5Q46gYRjLvampDXSmN8+icu54aRE3IIT8U+1w==", + "requires": { + "@babel/core": "^7.17.7", + "@babel/generator": "^7.17.7", + "@babel/parser": "^7.17.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", + "javascript-natural-sort": "0.7.1", + "lodash.clone": "^4.5.0", + "lodash.isequal": "^4.5.0" + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -11351,135 +11435,163 @@ "dev": true }, "@jest/console": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.1.tgz", - "integrity": "sha512-0RiUocPVFEm3WRMOStIHbRWllG6iW6E3/gUPnf4lkrVFyXIIDeCe+vlKeYyFOMhB2EPE6FLFCNADSOOQMaqvyA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz", + "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==", "dev": true, "requires": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^28.1.1", - "jest-util": "^28.1.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", "slash": "^3.0.0" } }, "@jest/core": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-28.1.1.tgz", - "integrity": "sha512-3pYsBoZZ42tXMdlcFeCc/0j9kOlK7MYuXs2B1QbvDgMoW1K9NJ4G/VYvIbMb26iqlkTfPHo7SC2JgjDOk/mxXw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz", + "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==", "dev": true, "requires": { - "@jest/console": "^28.1.1", - "@jest/reporters": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/console": "^29.3.1", + "@jest/reporters": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^28.0.2", - "jest-config": "^28.1.1", - "jest-haste-map": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.1", - "jest-resolve-dependencies": "^28.1.1", - "jest-runner": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-snapshot": "^28.1.1", - "jest-util": "^28.1.1", - "jest-validate": "^28.1.1", - "jest-watcher": "^28.1.1", + "jest-changed-files": "^29.2.0", + "jest-config": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-resolve-dependencies": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", + "jest-watcher": "^29.3.1", "micromatch": "^4.0.4", - "pretty-format": "^28.1.1", - "rimraf": "^3.0.0", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } } }, "@jest/environment": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-28.1.1.tgz", - "integrity": "sha512-9auVQ2GzQ7nrU+lAr8KyY838YahElTX9HVjbQPPS2XjlxQ+na18G113OoBhyBGBtD6ZnO/SrUy5WR8EzOj1/Uw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz", + "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==", "dev": true, "requires": { - "@jest/fake-timers": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-mock": "^28.1.1" + "jest-mock": "^29.3.1" + }, + "dependencies": { + "jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "requires": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + } + } } }, "@jest/expect": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-28.1.1.tgz", - "integrity": "sha512-/+tQprrFoT6lfkMj4mW/mUIfAmmk/+iQPmg7mLDIFOf2lyf7EBHaS+x3RbeR0VZVMe55IvX7QRoT/2aK3AuUXg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz", + "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==", "dev": true, "requires": { - "expect": "^28.1.1", - "jest-snapshot": "^28.1.1" + "expect": "^29.3.1", + "jest-snapshot": "^29.3.1" } }, "@jest/expect-utils": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-28.1.1.tgz", - "integrity": "sha512-n/ghlvdhCdMI/hTcnn4qV57kQuV9OTsZzH1TTCVARANKhl6hXJqLKUkwX69ftMGpsbpt96SsDD8n8LD2d9+FRw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz", + "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==", "dev": true, "requires": { - "jest-get-type": "^28.0.2" + "jest-get-type": "^29.2.0" } }, "@jest/fake-timers": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-28.1.1.tgz", - "integrity": "sha512-BY/3+TyLs5+q87rGWrGUY5f8e8uC3LsVHS9Diz8+FV3ARXL4sNnkLlIB8dvDvRrp+LUCGM+DLqlsYubizGUjIA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz", + "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==", "dev": true, "requires": { - "@jest/types": "^28.1.1", - "@sinonjs/fake-timers": "^9.1.1", + "@jest/types": "^29.3.1", + "@sinonjs/fake-timers": "^9.1.2", "@types/node": "*", - "jest-message-util": "^28.1.1", - "jest-mock": "^28.1.1", - "jest-util": "^28.1.1" + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" + }, + "dependencies": { + "jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "requires": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + } + } } }, "@jest/globals": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-28.1.1.tgz", - "integrity": "sha512-dEgl/6v7ToB4vXItdvcltJBgny0xBE6xy6IYQrPJAJggdEinGxCDMivNv7sFzPcTITGquXD6UJwYxfJ/5ZwDSg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz", + "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==", "dev": true, "requires": { - "@jest/environment": "^28.1.1", - "@jest/expect": "^28.1.1", - "@jest/types": "^28.1.1" + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/types": "^29.3.1", + "jest-mock": "^29.3.1" + }, + "dependencies": { + "jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "requires": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + } + } } }, "@jest/reporters": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-28.1.1.tgz", - "integrity": "sha512-597Zj4D4d88sZrzM4atEGLuO7SdA/YrOv9SRXHXRNC+/FwPCWxZhBAEzhXoiJzfRwn8zes/EjS8Lo6DouGN5Gg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz", + "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", - "@jridgewell/trace-mapping": "^0.3.7", + "@jest/console": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", + "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -11491,87 +11603,92 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^28.1.1", - "jest-util": "^28.1.1", - "jest-worker": "^28.1.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^9.0.0" + "v8-to-istanbul": "^9.0.1" } }, "@jest/schemas": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.0.2.tgz", - "integrity": "sha512-YVDJZjd4izeTDkij00vHHAymNXQ6WWsdChFRK86qck6Jpr3DCL5W3Is3vslviRlP+bLuMYRLbdp98amMvqudhA==", + "version": "29.0.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", + "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", "dev": true, "requires": { - "@sinclair/typebox": "^0.23.3" + "@sinclair/typebox": "^0.24.1" } }, "@jest/source-map": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-28.0.2.tgz", - "integrity": "sha512-Y9dxC8ZpN3kImkk0LkK5XCEneYMAXlZ8m5bflmSL5vrwyeUpJfentacCUg6fOb8NOpOO7hz2+l37MV77T6BFPw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz", + "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.7", + "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "@jest/test-result": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.1.tgz", - "integrity": "sha512-hPmkugBktqL6rRzwWAtp1JtYT4VHwv8OQ+9lE5Gymj6dHzubI/oJHMUpPOt8NrdVWSrz9S7bHjJUmv2ggFoUNQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz", + "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==", "dev": true, "requires": { - "@jest/console": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/console": "^29.3.1", + "@jest/types": "^29.3.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-28.1.1.tgz", - "integrity": "sha512-nuL+dNSVMcWB7OOtgb0EGH5AjO4UBCt68SLP08rwmC+iRhyuJWS9MtZ/MpipxFwKAlHFftbMsydXqWre8B0+XA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz", + "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==", "dev": true, "requires": { - "@jest/test-result": "^28.1.1", + "@jest/test-result": "^29.3.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.1", + "jest-haste-map": "^29.3.1", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-28.1.1.tgz", - "integrity": "sha512-PkfaTUuvjUarl1EDr5ZQcCA++oXkFCP9QFUkG0yVKVmNObjhrqDy0kbMpMebfHWm3CCDHjYNem9eUSH8suVNHQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", + "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^28.1.1", - "@jridgewell/trace-mapping": "^0.3.7", + "@jest/types": "^29.3.1", + "@jridgewell/trace-mapping": "^0.3.15", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.1", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.1", + "jest-haste-map": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^4.0.1" }, "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "write-file-atomic": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.1.tgz", - "integrity": "sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "requires": { "imurmurhash": "^0.1.4", @@ -11581,12 +11698,12 @@ } }, "@jest/types": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.1.tgz", - "integrity": "sha512-vRXVqSg1VhDnB8bWcmvLzmg0Bt9CRKVgHPXqYwvWMX3TvAjeO+nRuK6+VdTKCtWOvYlmkF/HqNAL/z+N3B53Kw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", + "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", + "@jest/schemas": "^29.0.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -11603,7 +11720,6 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -11611,31 +11727,27 @@ } }, "@jridgewell/resolve-uri": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.4.tgz", - "integrity": "sha512-cz8HFjOFfUBtvN+NXYSFMHYRdxZMaEl0XypVrhzxBgadKIXhIkRd8aMeHhmF56Sl7SuS8OnUpQ73/k9LE4VnLg==", - "dev": true + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" }, "@jridgewell/set-array": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", - "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", - "dev": true + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==" }, "@jridgewell/sourcemap-codec": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.10.tgz", - "integrity": "sha512-Ht8wIW5v165atIX1p+JvKR5ONzUyF4Ac8DZIQ5kZs9zrb6M8SJNXpx1zn04rn65VjBMygRoMXcyYwNK0fT7bEg==", - "dev": true + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", - "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", - "dev": true, + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, "@newrelic/aws-sdk": { @@ -11906,15 +12018,15 @@ } }, "@sinclair/typebox": { - "version": "0.23.5", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.23.5.tgz", - "integrity": "sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==", + "version": "0.24.51", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", + "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", "dev": true }, "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -11962,9 +12074,9 @@ } }, "@types/babel__core": { - "version": "7.1.19", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", - "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "version": "7.1.20", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", + "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -11994,9 +12106,9 @@ } }, "@types/babel__traverse": { - "version": "7.17.1", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", - "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", + "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -12144,13 +12256,13 @@ } }, "@types/jest": { - "version": "28.1.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-28.1.2.tgz", - "integrity": "sha512-5dNM7mMuIrCtNJsFfvUO/5xCrG8swuT2c7ND+sl3XwlwxJf3k7e7o+PRvcFN/iIm8XhCqHqxLOj9yutDDOJoRg==", + "version": "29.2.4", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.2.4.tgz", + "integrity": "sha512-PipFB04k2qTRPePduVLTRiPzQfvMeLwUN3Z21hsAKaB/W9IIzgB2pizCL466ftJlcyZqnHoC9ZHpxLGl3fS86A==", "dev": true, "requires": { - "jest-matcher-utils": "^28.0.0", - "pretty-format": "^28.0.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "@types/keygrip": { @@ -12235,9 +12347,9 @@ } }, "@types/prettier": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", - "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==", "dev": true }, "@types/qs": { @@ -12566,15 +12678,15 @@ } }, "babel-jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-28.1.1.tgz", - "integrity": "sha512-MEt0263viUdAkTq5D7upHPNxvt4n9uLUGa6pPz3WviNBMtOmStb1lIXS3QobnoqM+qnH+vr4EKlvhe8QcmxIYw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz", + "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==", "dev": true, "requires": { - "@jest/transform": "^28.1.1", + "@jest/transform": "^29.3.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^28.1.1", + "babel-preset-jest": "^29.2.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -12603,9 +12715,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.1.tgz", - "integrity": "sha512-NovGCy5Hn25uMJSAU8FaHqzs13cFoOI4lhIujiepssjCKRsAo3TA734RDWSGxuFTsUJXerYOqQQodlxgmtqbzw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz", + "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -12673,12 +12785,12 @@ } }, "babel-preset-jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-28.1.1.tgz", - "integrity": "sha512-FCq9Oud0ReTeWtcneYf/48981aTfXYuB9gbU4rBNNJVBSQ6ssv7E6v/qvbBxtOWwZFXjLZwpg+W3q7J6vhH25g==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz", + "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^28.1.1", + "babel-plugin-jest-hoist": "^29.2.0", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -12797,7 +12909,6 @@ "version": "4.20.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", - "dev": true, "requires": { "caniuse-lite": "^1.0.30001349", "electron-to-chromium": "^1.4.147", @@ -12893,8 +13004,7 @@ "caniuse-lite": { "version": "1.0.30001358", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001358.tgz", - "integrity": "sha512-hvp8PSRymk85R20bsDra7ZTCpSVGN/PAz9pSAjPSjKC+rNmnUk5vCRgJwiTT/O4feQ/yu/drvZYpKxxhbFuChw==", - "dev": true + "integrity": "sha512-hvp8PSRymk85R20bsDra7ZTCpSVGN/PAz9pSAjPSjKC+rNmnUk5vCRgJwiTT/O4feQ/yu/drvZYpKxxhbFuChw==" }, "chalk": { "version": "4.1.2", @@ -12943,9 +13053,9 @@ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "ci-info": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", - "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.0.tgz", + "integrity": "sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog==", "dev": true }, "cjs-module-lexer": { @@ -13193,7 +13303,6 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -13387,9 +13496,9 @@ "dev": true }, "diff-sequences": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-28.1.1.tgz", - "integrity": "sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz", + "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==", "dev": true }, "dot-prop": { @@ -13449,13 +13558,12 @@ "electron-to-chromium": { "version": "1.4.164", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.164.tgz", - "integrity": "sha512-K7iy5y6XyP9Pzh3uaDti0KC4JUNT6T1tLG5RTOmesqq2YgAJpYYYJ32m+anvZYjCV35llPTEh87kvEV/uSsiyQ==", - "dev": true + "integrity": "sha512-K7iy5y6XyP9Pzh3uaDti0KC4JUNT6T1tLG5RTOmesqq2YgAJpYYYJ32m+anvZYjCV35llPTEh87kvEV/uSsiyQ==" }, "emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true }, "emoji-regex": { @@ -13547,8 +13655,7 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "esm": { "version": "3.2.25", @@ -13606,16 +13713,16 @@ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, "expect": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-28.1.1.tgz", - "integrity": "sha512-/AANEwGL0tWBwzLNOvO0yUdy2D52jVdNXppOqswC49sxMN2cPWsGCQdzuIf9tj6hHoBQzNvx75JUYuQAckPo3w==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz", + "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==", "dev": true, "requires": { - "@jest/expect-utils": "^28.1.1", - "jest-get-type": "^28.0.2", - "jest-matcher-utils": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-util": "^28.1.1" + "@jest/expect-utils": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1" } }, "express": { @@ -13737,9 +13844,9 @@ "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" }, "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "requires": { "bser": "2.1.1" @@ -13935,8 +14042,7 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "get-caller-file": { "version": "2.0.5", @@ -14004,8 +14110,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "google-auth-library": { "version": "7.14.1", @@ -14359,9 +14464,9 @@ "dev": true }, "istanbul-lib-instrument": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", - "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "requires": { "@babel/core": "^7.12.3", @@ -14413,133 +14518,149 @@ } }, "istanbul-reports": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", - "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "requires": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, + "javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, "jest": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-28.1.1.tgz", - "integrity": "sha512-qw9YHBnjt6TCbIDMPMpJZqf9E12rh6869iZaN08/vpOGgHJSAaLLUn6H8W3IAEuy34Ls3rct064mZLETkxJ2XA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz", + "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==", "dev": true, "requires": { - "@jest/core": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/core": "^29.3.1", + "@jest/types": "^29.3.1", "import-local": "^3.0.2", - "jest-cli": "^28.1.1" + "jest-cli": "^29.3.1" } }, "jest-changed-files": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-28.0.2.tgz", - "integrity": "sha512-QX9u+5I2s54ZnGoMEjiM2WeBvJR2J7w/8ZUmH2um/WLAuGAYFQcsVXY9+1YL6k0H/AGUdH8pXUAv6erDqEsvIA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz", + "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==", "dev": true, "requires": { "execa": "^5.0.0", - "throat": "^6.0.1" + "p-limit": "^3.1.0" } }, "jest-circus": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-28.1.1.tgz", - "integrity": "sha512-75+BBVTsL4+p2w198DQpCeyh1RdaS2lhEG87HkaFX/UG0gJExVq2skG2pT7XZEGBubNj2CytcWSPan4QEPNosw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz", + "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==", "dev": true, "requires": { - "@jest/environment": "^28.1.1", - "@jest/expect": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/environment": "^29.3.1", + "@jest/expect": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^28.1.1", - "jest-matcher-utils": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-snapshot": "^28.1.1", - "jest-util": "^28.1.1", - "pretty-format": "^28.1.1", + "jest-each": "^29.3.1", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", + "p-limit": "^3.1.0", + "pretty-format": "^29.3.1", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-28.1.1.tgz", - "integrity": "sha512-+sUfVbJqb1OjBZ0OdBbI6OWfYM1i7bSfzYy6gze1F1w3OKWq8ZTEKkZ8a7ZQPq6G/G1qMh/uKqpdWhgl11NFQQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz", + "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==", "dev": true, "requires": { - "@jest/core": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/core": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^28.1.1", - "jest-util": "^28.1.1", - "jest-validate": "^28.1.1", + "jest-config": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "prompts": "^2.0.1", "yargs": "^17.3.1" }, "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "yargs": { - "version": "17.5.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", - "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true } } }, "jest-config": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-28.1.1.tgz", - "integrity": "sha512-tASynMhS+jVV85zKvjfbJ8nUyJS/jUSYZ5KQxLUN2ZCvcQc/OmhQl2j6VEL3ezQkNofxn5pQ3SPYWPHb0unTZA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz", + "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^28.1.1", - "@jest/types": "^28.1.1", - "babel-jest": "^28.1.1", + "@jest/test-sequencer": "^29.3.1", + "@jest/types": "^29.3.1", + "babel-jest": "^29.3.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^28.1.1", - "jest-environment-node": "^28.1.1", - "jest-get-type": "^28.0.2", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.1", - "jest-runner": "^28.1.1", - "jest-util": "^28.1.1", - "jest-validate": "^28.1.1", + "jest-circus": "^29.3.1", + "jest-environment-node": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-runner": "^29.3.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^28.1.1", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -14553,75 +14674,88 @@ } }, "jest-diff": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-28.1.1.tgz", - "integrity": "sha512-/MUUxeR2fHbqHoMMiffe/Afm+U8U4olFRJ0hiVG2lZatPJcnGxx292ustVu7bULhjV65IYMxRdploAKLbcrsyg==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz", + "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.1" + "diff-sequences": "^29.3.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" } }, "jest-docblock": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-28.1.1.tgz", - "integrity": "sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz", + "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-28.1.1.tgz", - "integrity": "sha512-A042rqh17ZvEhRceDMi784ppoXR7MWGDEKTXEZXb4svt0eShMZvijGxzKsx+yIjeE8QYmHPrnHiTSQVhN4nqaw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz", + "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==", "dev": true, "requires": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", - "jest-util": "^28.1.1", - "pretty-format": "^28.1.1" + "jest-get-type": "^29.2.0", + "jest-util": "^29.3.1", + "pretty-format": "^29.3.1" } }, "jest-environment-node": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-28.1.1.tgz", - "integrity": "sha512-2aV/eeY/WNgUUJrrkDJ3cFEigjC5fqT1+fCclrY6paqJ5zVPoM//sHmfgUUp7WLYxIdbPwMiVIzejpN56MxnNA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz", + "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==", "dev": true, "requires": { - "@jest/environment": "^28.1.1", - "@jest/fake-timers": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", - "jest-mock": "^28.1.1", - "jest-util": "^28.1.1" + "jest-mock": "^29.3.1", + "jest-util": "^29.3.1" + }, + "dependencies": { + "jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "requires": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + } + } } }, "jest-get-type": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-28.0.2.tgz", - "integrity": "sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz", + "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==", "dev": true }, "jest-haste-map": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-28.1.1.tgz", - "integrity": "sha512-ZrRSE2o3Ezh7sb1KmeLEZRZ4mgufbrMwolcFHNRSjKZhpLa8TdooXOOFlSwoUzlbVs1t0l7upVRW2K7RWGHzbQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", + "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", "dev": true, "requires": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^28.0.2", - "jest-util": "^28.1.1", - "jest-worker": "^28.1.1", + "jest-regex-util": "^29.2.0", + "jest-util": "^29.3.1", + "jest-worker": "^29.3.1", "micromatch": "^4.0.4", "walker": "^1.0.8" } @@ -14639,40 +14773,40 @@ } }, "jest-leak-detector": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-28.1.1.tgz", - "integrity": "sha512-4jvs8V8kLbAaotE+wFR7vfUGf603cwYtFf1/PYEsyX2BAjSzj8hQSVTP6OWzseTl0xL6dyHuKs2JAks7Pfubmw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz", + "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==", "dev": true, "requires": { - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.1" + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" } }, "jest-matcher-utils": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-28.1.1.tgz", - "integrity": "sha512-NPJPRWrbmR2nAJ+1nmnfcKKzSwgfaciCCrYZzVnNoxVoyusYWIjkBMNvu0RHJe7dNj4hH3uZOPZsQA+xAYWqsw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz", + "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^28.1.1", - "jest-get-type": "^28.0.2", - "pretty-format": "^28.1.1" + "jest-diff": "^29.3.1", + "jest-get-type": "^29.2.0", + "pretty-format": "^29.3.1" } }, "jest-message-util": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.1.tgz", - "integrity": "sha512-xoDOOT66fLfmTRiqkoLIU7v42mal/SqwDKvfmfiWAdJMSJiU+ozgluO7KbvoAgiwIrrGZsV7viETjc8GNrA/IQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz", + "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^28.1.1", + "pretty-format": "^29.3.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" } @@ -14685,142 +14819,181 @@ "requires": { "@jest/types": "^28.1.1", "@types/node": "*" + }, + "dependencies": { + "@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.24.1" + } + }, + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "dev": true, + "requires": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + } } }, "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "requires": {} }, "jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", + "version": "29.2.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", + "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", "dev": true }, "jest-resolve": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-28.1.1.tgz", - "integrity": "sha512-/d1UbyUkf9nvsgdBildLe6LAD4DalgkgZcKd0nZ8XUGPyA/7fsnaQIlKVnDiuUXv/IeZhPEDrRJubVSulxrShA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz", + "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.1", + "jest-haste-map": "^29.3.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^28.1.1", - "jest-validate": "^28.1.1", + "jest-util": "^29.3.1", + "jest-validate": "^29.3.1", "resolve": "^1.20.0", "resolve.exports": "^1.1.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.1.tgz", - "integrity": "sha512-p8Y150xYJth4EXhOuB8FzmS9r8IGLEioiaetgdNGb9VHka4fl0zqWlVe4v7mSkYOuEUg2uB61iE+zySDgrOmgQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz", + "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==", "dev": true, "requires": { - "jest-regex-util": "^28.0.2", - "jest-snapshot": "^28.1.1" + "jest-regex-util": "^29.2.0", + "jest-snapshot": "^29.3.1" } }, "jest-runner": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-28.1.1.tgz", - "integrity": "sha512-W5oFUiDBgTsCloTAj6q95wEvYDB0pxIhY6bc5F26OucnwBN+K58xGTGbliSMI4ChQal5eANDF+xvELaYkJxTmA==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz", + "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==", "dev": true, "requires": { - "@jest/console": "^28.1.1", - "@jest/environment": "^28.1.1", - "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/console": "^29.3.1", + "@jest/environment": "^29.3.1", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.10.2", + "emittery": "^0.13.1", "graceful-fs": "^4.2.9", - "jest-docblock": "^28.1.1", - "jest-environment-node": "^28.1.1", - "jest-haste-map": "^28.1.1", - "jest-leak-detector": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-resolve": "^28.1.1", - "jest-runtime": "^28.1.1", - "jest-util": "^28.1.1", - "jest-watcher": "^28.1.1", - "jest-worker": "^28.1.1", - "source-map-support": "0.5.13", - "throat": "^6.0.1" + "jest-docblock": "^29.2.0", + "jest-environment-node": "^29.3.1", + "jest-haste-map": "^29.3.1", + "jest-leak-detector": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-resolve": "^29.3.1", + "jest-runtime": "^29.3.1", + "jest-util": "^29.3.1", + "jest-watcher": "^29.3.1", + "jest-worker": "^29.3.1", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-28.1.1.tgz", - "integrity": "sha512-J89qEJWW0leOsqyi0D9zHpFEYHwwafFdS9xgvhFHtIdRghbadodI0eA+DrthK/1PebBv3Px8mFSMGKrtaVnleg==", - "dev": true, - "requires": { - "@jest/environment": "^28.1.1", - "@jest/fake-timers": "^28.1.1", - "@jest/globals": "^28.1.1", - "@jest/source-map": "^28.0.2", - "@jest/test-result": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz", + "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==", + "dev": true, + "requires": { + "@jest/environment": "^29.3.1", + "@jest/fake-timers": "^29.3.1", + "@jest/globals": "^29.3.1", + "@jest/source-map": "^29.2.0", + "@jest/test-result": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", + "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-mock": "^28.1.1", - "jest-regex-util": "^28.0.2", - "jest-resolve": "^28.1.1", - "jest-snapshot": "^28.1.1", - "jest-util": "^28.1.1", + "jest-haste-map": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-mock": "^29.3.1", + "jest-regex-util": "^29.2.0", + "jest-resolve": "^29.3.1", + "jest-snapshot": "^29.3.1", + "jest-util": "^29.3.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" + }, + "dependencies": { + "jest-mock": { + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz", + "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==", + "dev": true, + "requires": { + "@jest/types": "^29.3.1", + "@types/node": "*", + "jest-util": "^29.3.1" + } + } } }, "jest-snapshot": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-28.1.1.tgz", - "integrity": "sha512-1KjqHJ98adRcbIdMizjF5DipwZFbvxym/kFO4g4fVZCZRxH/dqV8TiBFCa6rqic3p0karsy8RWS1y4E07b7P0A==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz", + "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^28.1.1", - "@jest/transform": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/expect-utils": "^29.3.1", + "@jest/transform": "^29.3.1", + "@jest/types": "^29.3.1", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^28.1.1", + "expect": "^29.3.1", "graceful-fs": "^4.2.9", - "jest-diff": "^28.1.1", - "jest-get-type": "^28.0.2", - "jest-haste-map": "^28.1.1", - "jest-matcher-utils": "^28.1.1", - "jest-message-util": "^28.1.1", - "jest-util": "^28.1.1", + "jest-diff": "^29.3.1", + "jest-get-type": "^29.2.0", + "jest-haste-map": "^29.3.1", + "jest-matcher-utils": "^29.3.1", + "jest-message-util": "^29.3.1", + "jest-util": "^29.3.1", "natural-compare": "^1.4.0", - "pretty-format": "^28.1.1", + "pretty-format": "^29.3.1", "semver": "^7.3.5" }, "dependencies": { "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -14829,12 +15002,12 @@ } }, "jest-util": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.1.tgz", - "integrity": "sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", + "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", "dev": true, "requires": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -14843,17 +15016,17 @@ } }, "jest-validate": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-28.1.1.tgz", - "integrity": "sha512-Kpf6gcClqFCIZ4ti5++XemYJWUPCFUW+N2gknn+KgnDf549iLul3cBuKVe1YcWRlaF8tZV8eJCap0eECOEE3Ug==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz", + "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==", "dev": true, "requires": { - "@jest/types": "^28.1.1", + "@jest/types": "^29.3.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^28.0.2", + "jest-get-type": "^29.2.0", "leven": "^3.1.0", - "pretty-format": "^28.1.1" + "pretty-format": "^29.3.1" }, "dependencies": { "camelcase": { @@ -14865,28 +15038,29 @@ } }, "jest-watcher": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.1.tgz", - "integrity": "sha512-RQIpeZ8EIJMxbQrXpJQYIIlubBnB9imEHsxxE41f54ZwcqWLysL/A0ZcdMirf+XsMn3xfphVQVV4EW0/p7i7Ug==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz", + "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==", "dev": true, "requires": { - "@jest/test-result": "^28.1.1", - "@jest/types": "^28.1.1", + "@jest/test-result": "^29.3.1", + "@jest/types": "^29.3.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.1", + "emittery": "^0.13.1", + "jest-util": "^29.3.1", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.1.tgz", - "integrity": "sha512-Au7slXB08C6h+xbJPp7VIb6U0XX5Kc9uel/WFc6/rcTzGiaVCBRngBExSYuXSLFPULPSYU3cJ3ybS988lNFQhQ==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", + "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.3.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } @@ -14894,8 +15068,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.14.1", @@ -14910,8 +15083,7 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json-bigint": { "version": "1.0.0", @@ -14935,8 +15107,7 @@ "json5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, "jsonfile": { "version": "4.0.0", @@ -15097,16 +15268,26 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, "lodash.sortby": { @@ -15503,8 +15684,7 @@ "node-releases": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", - "dev": true + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" }, "nodemailer": { "version": "6.7.5", @@ -15836,8 +16016,7 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { "version": "2.3.1", @@ -15906,14 +16085,18 @@ "tunnel-agent": "^0.6.0" } }, + "prettier": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.0.tgz", + "integrity": "sha512-9Lmg8hTFZKG0Asr/kW9Bp8tJjRVluO8EJQVfY2T7FMw9T5jy4I/Uvx0Rca/XWf50QQ1/SS48+6IJWnrb+2yemA==" + }, "pretty-format": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.1.tgz", - "integrity": "sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw==", + "version": "29.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz", + "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==", "dev": true, "requires": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.0.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -16473,9 +16656,9 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "requires": { "escape-string-regexp": "^2.0.0" @@ -16578,27 +16761,6 @@ "has-flag": "^4.0.0" } }, - "supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "tar-fs": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", @@ -16656,16 +16818,6 @@ } } }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -16682,12 +16834,6 @@ "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" }, - "throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -16715,8 +16861,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "to-regex-range": { "version": "5.0.1", @@ -16747,14 +16892,14 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "ts-jest": { - "version": "28.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-28.0.5.tgz", - "integrity": "sha512-Sx9FyP9pCY7pUzQpy4FgRZf2bhHY3za576HMKJFs+OnQ9jS96Du5vNsDKkyedQkik+sEabbKAnCliv9BEsHZgQ==", + "version": "29.0.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz", + "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==", "dev": true, "requires": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", - "jest-util": "^28.0.0", + "jest-util": "^29.0.0", "json5": "^2.2.1", "lodash.memoize": "4.x", "make-error": "1.x", @@ -16763,18 +16908,18 @@ }, "dependencies": { "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "requires": { "lru-cache": "^6.0.0" } }, "yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true } } @@ -16899,9 +17044,9 @@ } }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true }, "unicode-canonical-property-names-ecmascript": { diff --git a/backend/package.json b/backend/package.json index 8042a6b3d..1085fd013 100644 --- a/backend/package.json +++ b/backend/package.json @@ -59,6 +59,7 @@ "dependencies": { "@devoxa/prisma-relay-cursor-connection": "^2.2.1", "@google-cloud/storage": "^5.19.1", + "@ianvs/prettier-plugin-sort-imports": "^3.7.1", "@prisma/client": "2.23", "@sentry/integrations": "^6.19.6", "@sentry/node": "^6.19.6", @@ -109,7 +110,7 @@ "@types/express": "^4.17.12", "@types/faker": "^5.5.9", "@types/graphql-upload": "^8.0.12", - "@types/jest": "^28.1.2", + "@types/jest": "^29.2.4", "@types/lodash": "^4.14.190", "@types/luxon": "^3.1.0", "@types/mime-types": "^2.1.1", @@ -123,16 +124,17 @@ "get-port": "^5.0.0", "graceful-fs": "^4.2.10", "graphql-request": "^4.3.0", - "jest": "^28.1.1", + "jest": "^29.3.1", "jest-junit": "^13.2.0", "jest-mock": "^28.1.1", "locate-path": "^7.1.1", "nanoid": "^3.3.2", "nock": "^13.2.7", - "ts-jest": "^28.0.5", + "prettier": "^2.8.0", + "ts-jest": "^29.0.3", "ts-node": "^10.8.1", "ts-node-dev": "^2.0.0", - "typescript": "^4.7.4" + "typescript": "^4.9.4" }, "overrides": { "graphql": "16.5.0" diff --git a/backend/prisma/schema.prisma b/backend/prisma/schema.prisma index 8283ac122..12ecd0227 100644 --- a/backend/prisma/schema.prisma +++ b/backend/prisma/schema.prisma @@ -1,5 +1,6 @@ generator client { provider = "prisma-client-js" + previewFeatures = ["orderByRelation", "selectRelationCount", "orderByAggregateGroup", "filterJson"] } datasource db { @@ -130,6 +131,7 @@ model Course { ownerships CourseOwnership[] course_stats_email_id String? course_stats_email EmailTemplate? @relation("courseTocourse_course_stats_email", fields: [course_stats_email_id], references: [id]) + course_tags CourseTag[] @@map("course") } @@ -562,6 +564,53 @@ model CourseStatsSubscription { @@map("course_stats_subscription") } +model Tag { + created_at DateTime? @default(now()) + updated_at DateTime? @updatedAt + id String @id @default(uuid()) + hidden Boolean? @default(false) + tag_types TagType[] + tag_translations TagTranslation[] + course_tags CourseTag[] + + @@map("tag") +} + +model TagType { + created_at DateTime? @default(now()) + updated_at DateTime? @updatedAt + name String @id + tags Tag[] + + @@map("tag_type") +} + +model TagTranslation { + created_at DateTime? @default(now()) + updated_at DateTime? @updatedAt + tag_id String + language String + name String + description String? + tag Tag @relation(fields: [tag_id], references: [id]) + + @@id([tag_id, language]) + @@unique([name, language]) + @@map("tag_translation") +} + +model CourseTag { + created_at DateTime? @default(now()) + updated_at DateTime? @updatedAt + course_id String + tag_id String + course Course @relation(fields: [course_id], references: [id]) + tag Tag @relation(fields: [tag_id], references: [id]) + + @@id([course_id, tag_id]) + @@map("course_tag") +} + enum CourseStatus { Active Ended diff --git a/backend/schema.ts b/backend/schema.ts index 38482df1c..7d2a89ba0 100644 --- a/backend/schema.ts +++ b/backend/schema.ts @@ -11,6 +11,7 @@ import * as types from "./graphql" import { cachePlugin } from "./middlewares/cache" import { moocfiAuthPlugin } from "./middlewares/fetchUser" import { loggerPlugin } from "./middlewares/logger" +import { validateArgsPlugin } from "./middlewares/validate" if (NEXUS_REFLECTION) { require("sharp") @@ -48,6 +49,7 @@ const createPlugins = () => { cachePlugin(), moocfiAuthPlugin(), fieldAuthorizePlugin(), + validateArgsPlugin(), ] if (isProduction && !NEXUS_REFLECTION && NEW_RELIC_LICENSE_KEY) { @@ -60,33 +62,40 @@ const createPlugins = () => { return plugins } -export default makeSchema({ - types, - contextType: { - module: join(process.cwd(), "context.ts"), - export: "Context", - }, - sourceTypes: { - modules: [ - { - module: require.resolve(".prisma/client/index.d.ts"), - alias: "prisma", +const createSchema = () => + makeSchema({ + types, + contextType: { + module: join(process.cwd(), "context.ts"), + export: "Context", + }, + sourceTypes: { + modules: [ + { + module: require.resolve(".prisma/client/index.d.ts"), + alias: "prisma", + }, + { module: "@types/graphql-upload/index.d.ts", alias: "upload" }, + ], + mapping: { + Upload: "upload.Upload['promise']", }, - { module: "@types/graphql-upload/index.d.ts", alias: "upload" }, - ], - mapping: { - Upload: "upload.Upload['promise']", }, - }, - plugins: createPlugins(), - outputs: { - typegen: path.join( - __dirname, - "./node_modules/@types/nexus-typegen/index.d.ts", - ), - schema: __dirname + "/generated/schema.graphql", - }, - prettierConfig: path.join(__dirname, "../.prettierrc.js"), - shouldGenerateArtifacts: true, - shouldExitAfterGenerateArtifacts: Boolean(NEXUS_REFLECTION), -}) + plugins: createPlugins(), + outputs: { + typegen: path.join( + __dirname, + "./node_modules/@types/nexus-typegen/index.d.ts", + ), + schema: __dirname + "/generated/schema.graphql", + }, + // prettierConfig: path.join(__dirname, "/.prettierrc.js"), + shouldGenerateArtifacts: true, + shouldExitAfterGenerateArtifacts: Boolean(NEXUS_REFLECTION), + }) + +if (NEXUS_REFLECTION) { + createSchema() +} + +export default createSchema diff --git a/backend/server.ts b/backend/server.ts index 19b5934b7..76c707267 100644 --- a/backend/server.ts +++ b/backend/server.ts @@ -8,7 +8,7 @@ import morgan from "morgan" import { apiRouter } from "./api" import { DEBUG, isProduction, isTest } from "./config" import { ServerContext } from "./context" -import schema from "./schema" +import createSchema from "./schema" const helmet = require("helmet") const bodyParser = require("body-parser") @@ -37,6 +37,7 @@ const createExpressAppWithContext = ({ export default async (serverContext: ServerContext) => { const { prisma, logger, knex, extraContext = {} } = serverContext + const schema = createSchema() const apollo = new ApolloServer({ context: (ctx) => ({ diff --git a/backend/services/tmc.ts b/backend/services/tmc.ts index 0f7e7bb66..d07d3e945 100644 --- a/backend/services/tmc.ts +++ b/backend/services/tmc.ts @@ -38,9 +38,9 @@ async function fetchAccessToken(): Promise { const response = await axios.post( `${TMC_HOST}/oauth/token`, `client_secret=${TMC_CLIENT_SECRET}&client_id=${TMC_CLIENT_ID}&username=${encodeURIComponent( - TMC_USERNAME || "", + TMC_USERNAME ?? "", )}&password=${encodeURIComponent( - TMC_PASSWORD || "", + TMC_PASSWORD ?? "", )}&grant_type=password`, { headers: { diff --git a/backend/tests/data/fixtures.ts b/backend/tests/data/fixtures.ts index 011a2b4f2..420aa1dc6 100644 --- a/backend/tests/data/fixtures.ts +++ b/backend/tests/data/fixtures.ts @@ -70,6 +70,8 @@ export const organizations: Prisma.OrganizationCreateInput[] = [ id: "10000000000000000000000000000102", secret_key: "kissa", slug: "test", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -85,15 +87,21 @@ export const study_modules: Prisma.StudyModuleCreateInput[] = [ description: "module1_en_US", language: "en_US", name: "module1_en_US", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "00000000000000000000000000001102", description: "module1_fi_FI", language: "fi_FI", name: "module1_fi_FI", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ], }, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "00000000000000000000000000000101", @@ -106,9 +114,13 @@ export const study_modules: Prisma.StudyModuleCreateInput[] = [ description: "module2_fi_FI", language: "fi_FI", name: "module2_fi_FI", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ], }, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -130,6 +142,8 @@ export const courses: Prisma.CourseCreateInput[] = [ language: "en_US", name: "course1_en_US", link: "http://link.com", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "00000000000000000000000000000012", @@ -138,6 +152,8 @@ export const courses: Prisma.CourseCreateInput[] = [ language: "fi_FI", name: "course1_fi_FI", link: "http:/link.fi.com", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ], }, @@ -156,11 +172,15 @@ export const courses: Prisma.CourseCreateInput[] = [ compressed_mimetype: "image/webp", uncompressed: "jpeg", uncompressed_mimetype: "image/jpeg", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, }, automatic_completions: true, points_needed: 3, exercise_completions_needed: 1, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "00000000000000000000000000000001", @@ -178,12 +198,16 @@ export const courses: Prisma.CourseCreateInput[] = [ instructions: "course2_instructions_fi_FI", language: "fi_FI", name: "course2_fi_FI", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ], }, study_modules: { connect: { id: "00000000000000000000000000000102" }, }, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "00000000-0000-0000-0000-000000000666", @@ -194,6 +218,8 @@ export const courses: Prisma.CourseCreateInput[] = [ teacher_in_charge_email: "t@mail.com", teacher_in_charge_name: "foo", hidden: false, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "00000000-0000-0000-0000-000000000667", @@ -207,6 +233,8 @@ export const courses: Prisma.CourseCreateInput[] = [ completions_handled_by: { connect: { id: "00000000000000000000000000000666" }, }, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "00000000-0000-0000-0000-000000000668", @@ -220,6 +248,8 @@ export const courses: Prisma.CourseCreateInput[] = [ inherit_settings_from: { connect: { id: "00000000000000000000000000000666" }, }, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -457,6 +487,8 @@ export const services: Prisma.ServiceCreateInput[] = [ courses: { connect: { id: "00000000000000000000000000000001" }, }, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -465,11 +497,15 @@ export const abStudies: Prisma.AbStudyCreateInput[] = [ id: "99000000-0000-0000-0000-000000000001", group_count: 3, name: "test_study", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "99000000-0000-0000-0000-000000000002", group_count: 2, name: "test_study2", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -478,11 +514,15 @@ export const abEnrollments: Prisma.AbEnrollmentCreateInput[] = [ user: { connect: { id: "20000000000000000000000000000103" } }, ab_study: { connect: { id: "99000000-0000-0000-0000-000000000002" } }, group: 2, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { user: { connect: { id: "20000000000000000000000000000102" } }, ab_study: { connect: { id: "99000000-0000-0000-0000-000000000002" } }, group: 3, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -498,6 +538,8 @@ export const exercises: Prisma.ExerciseCreateInput[] = [ part: 1, section: 1, deleted: false, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "50000000-0000-0000-0000-000000000002", @@ -510,6 +552,8 @@ export const exercises: Prisma.ExerciseCreateInput[] = [ part: 1, section: 2, deleted: false, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "50000000-0000-0000-0000-000000000003", @@ -520,6 +564,8 @@ export const exercises: Prisma.ExerciseCreateInput[] = [ timestamp: new Date("2021-01-01 10:00:00.00"), deleted: false, max_points: 3, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "50000000-0000-0000-0000-000000000004", @@ -529,6 +575,8 @@ export const exercises: Prisma.ExerciseCreateInput[] = [ custom_id: "customid4", timestamp: new Date("2021-01-01 10:00:00.00"), deleted: true, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "50000000-0000-0000-0000-000000000005", @@ -538,6 +586,8 @@ export const exercises: Prisma.ExerciseCreateInput[] = [ custom_id: "customid5", timestamp: new Date("2021-01-01 10:00:00.00"), deleted: true, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -697,6 +747,8 @@ export const userCourseServiceProgresses: Prisma.UserCourseServiceProgressCreate connect: { id: "40000000-0000-0000-0000-000000000102" }, }, progress: [{ group: "week1", max_points: 3, n_points: 3 }], + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -748,16 +800,22 @@ export const courseAliases: Prisma.CourseAliasCreateInput[] = [ id: "67000000-0000-0000-0000-000000000001", course: { connect: { id: "00000000000000000000000000000002" } }, course_code: "alias", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "67000000-0000-0000-0000-000000000002", course: { connect: { id: "00000000000000000000000000000001" } }, course_code: "alias2", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "67000000-0000-0000-0000-000000000003", course: { connect: { id: "00000000000000000000000000000666" } }, course_code: "alias3", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -789,6 +847,8 @@ export const openUniversityRegistrationLink: Prisma.OpenUniversityRegistrationLi ], }, ], + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "e3eea9b5-1ff1-47f8-94f4-269c7a092d92", @@ -797,6 +857,8 @@ export const openUniversityRegistrationLink: Prisma.OpenUniversityRegistrationLi course: { connect: { id: "00000000000000000000000000000001" } }, link: "avoin-link-alias2", tiers: null, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, { id: "e3eea9b5-1ff1-47f8-94f4-269c7a092d91", @@ -805,6 +867,8 @@ export const openUniversityRegistrationLink: Prisma.OpenUniversityRegistrationLi course: { connect: { id: "00000000000000000000000000000666" } }, link: "avoin-link-alias3", tiers: null, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", }, ] @@ -836,3 +900,106 @@ export const courseOwnerships: Prisma.CourseOwnershipCreateInput[] = [ updated_at: "1900-01-01T10:00:00.00+02:00", }, ] + +export const tagTypes: Prisma.TagTypeCreateInput[] = [ + { + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + name: "type1", + }, + { + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + name: "type2", + }, +] + +export const tags: Prisma.TagCreateInput[] = [ + { + id: "48100000-0000-0000-0000-000000000001", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + tag_types: { connect: { name: "type1" } }, + tag_translations: { + create: [ + { + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + language: "en_US", + name: "tag1 in english", + description: "tag1 description", + }, + { + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + language: "fi_FI", + name: "tag1 suomeksi", + description: "tag1 kuvaus", + }, + ], + }, + }, + { + id: "48100000-0000-0000-0000-000000000002", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + tag_types: { connect: [{ name: "type1" }, { name: "type2" }] }, + tag_translations: { + create: [ + { + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + language: "en_US", + name: "tag2 in english", + description: "tag2 description", + }, + { + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + language: "fi_FI", + name: "tag2 suomeksi", + description: "tag2 kuvaus ja jotain muuta", + }, + ], + }, + }, + { + id: "48100000-0000-0000-0000-000000000003", + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + tag_types: { connect: [{ name: "type2" }] }, + hidden: true, + tag_translations: { + create: [ + { + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + language: "fi_FI", + name: "piilotettu tag3", + description: "piilotettu tag3 kuvaus ja täts it", + }, + ], + }, + }, +] + +export const courseTags: Prisma.CourseTagCreateInput[] = [ + { + tag: { connect: { id: "48100000-0000-0000-0000-000000000001" } }, // tag1 + course: { connect: { id: "00000000000000000000000000000002" } }, // course1, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + }, + { + tag: { connect: { id: "48100000-0000-0000-0000-000000000002" } }, // tag2 + course: { connect: { id: "00000000000000000000000000000002" } }, // course1, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + }, + { + tag: { connect: { id: "48100000-0000-0000-0000-000000000003" } }, // hidden tag3 + course: { connect: { id: "00000000000000000000000000000001" } }, // course2, + created_at: "1900-01-01T10:00:00.00+02:00", + updated_at: "1900-01-01T10:00:00.00+02:00", + }, +] diff --git a/backend/tests/data/seed.ts b/backend/tests/data/seed.ts index 4f63996ad..c314ffdc4 100644 --- a/backend/tests/data/seed.ts +++ b/backend/tests/data/seed.ts @@ -8,6 +8,7 @@ import { courseAliases, courseOwnerships, courses, + courseTags, emailTemplateThresholds, exerciseCompletions, exercises, @@ -16,6 +17,8 @@ import { services, storedData, study_modules, + tags, + tagTypes, userCourseProgresses, userCourseServiceProgresses, userCourseSettings, @@ -81,6 +84,9 @@ export const seed = async (prisma: PrismaClient) => { "courseOwnership", courseOwnerships, ) + const seededTagTypes = await create("tagType", tagTypes) + const seededTags = await create("tag", tags) + const seededCourseTags = await create("courseTag", courseTags) return { courses: seededCourses, @@ -102,5 +108,8 @@ export const seed = async (prisma: PrismaClient) => { openUniversityRegistrationLink: seededOpenUniversityRegistrationLink, storedData: seededStoredData, courseOwnerships: seededCourseOwnerships, + tags: seededTags, + tagTypes: seededTagTypes, + courseTags: seededCourseTags, } } diff --git a/backend/tests/index.ts b/backend/tests/index.ts index b64395229..d5a8434cb 100644 --- a/backend/tests/index.ts +++ b/backend/tests/index.ts @@ -12,13 +12,10 @@ import { PrismaClient, User } from "@prisma/client" import { DATABASE_URL, DB_USER, DEBUG, EXTENSION_PATH } from "../config" import binPrisma from "../prisma" import server from "../server" +import { fail } from "./util" require("sharp") // ensure correct zlib thingy -export function fail(reason = "fail was called in a test") { - throw new Error(reason) -} - // @ts-ignore: jest has no explicit fail anymore global.fail = fail diff --git a/backend/tests/util/index.ts b/backend/tests/util/index.ts index 9c79537ef..3e6230086 100644 --- a/backend/tests/util/index.ts +++ b/backend/tests/util/index.ts @@ -1,2 +1,3 @@ export * from "./request" export * from "./tmc" +export * from "./jest" diff --git a/backend/tests/util/jest.ts b/backend/tests/util/jest.ts new file mode 100644 index 000000000..374da3db2 --- /dev/null +++ b/backend/tests/util/jest.ts @@ -0,0 +1,446 @@ +import { type MatcherContext } from "expect" +import { toMatchSnapshot, type Context } from "jest-snapshot" +import { omit } from "lodash" +import { DateTime } from "luxon" + +import { isNullOrUndefined } from "../../util/isNullOrUndefined" + +export const ID_REGEX = new RegExp( + /[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}/, + "i", +) + +export function fail(reason = "fail was called in a test") { + throw new Error(reason) +} + +const isObject = (value: unknown): value is Record => + typeof value === "object" && + !Array.isArray(value) && + value !== null && + !(value instanceof Date) && + !(value instanceof DateTime) + +export function stripDates(obj: T): T +export function stripDates(obj: T): Omit +export function stripDates(obj: null): null +export function stripDates( + obj: T | null, +): Omit | null +export function stripDates(obj: undefined): undefined +export function stripDates( + obj?: T | null, +): Omit | null | undefined { + if (!isObject(obj) || isNullOrUndefined(obj)) { + return obj + } + + const ret = omit(obj, ["created_at", "updated_at"]) as Omit< + T, + "created_at" | "updated_at" + > + + for (const key of Object.keys(obj) as Array) { + const value = obj[key] + if (Array.isArray(value)) { + ret[key] = value.map(stripDates) as (typeof value)[number] + } else if (isObject(value)) { + ret[key] = stripDates(value) + } + } + + return ret +} + +export type UnionToIntersection = ( + U extends any ? (k: U) => void : never +) extends (k: infer I) => void + ? I + : never + +type _DeepOmit = T extends object + ? P extends `${infer Head}.${infer Rest}` + ? { + [K in keyof T]: K extends Head ? DeepOmit : T[K] + } + : P extends `${infer Head}` + ? { + [K in keyof T]: K extends Head + ? never + : T[K] extends object + ? DeepOmit + : T[K] + } + : never + : never + +type DeepOmit = UnionToIntersection<_DeepOmit> + +export type Path = T extends Record + ? { + [K in keyof T & string]: + | K + | `${K}.${Path extends infer U extends string ? U : never}` + }[keyof T & string] + : T extends Array + ? { + [K in keyof R & string]: + | K + | `${K}.${Path extends infer U extends string ? U : never}` + }[keyof R & string] + : never + +type Field = T extends Record + ? { + [K in keyof T & string]: Field extends infer U extends string + ? K | U + : K + }[keyof T & string] + : T extends Array + ? { + [K in keyof R & string]: Field extends infer U extends string + ? K | U + : K + }[keyof R & string] + : never + +export function stripFields< + T, + Fields extends Array> = Array>, +>(obj: T, fields: Fields): DeepOmit { + if (Array.isArray(obj)) { + return obj.map((item: (T & any[])[number]) => + stripFields(item, fields), + ) as unknown as DeepOmit + } + + if (!isObject(obj) || isNullOrUndefined(obj)) { + return obj as DeepOmit + } + const ret = {} as DeepOmit + + for (const key of Object.keys(obj) as Array) { + const value = obj[key] + if (Array.isArray(value)) { + ret[key as keyof typeof ret] = value.map( + (item: (T[keyof T] & any[])[number]) => stripFields(item, fields), + ) as DeepOmit[keyof typeof ret] + } else if (isObject(value)) { + ret[key as keyof typeof ret] = omit(value, fields) as DeepOmit< + T, + Fields[number] + >[keyof typeof ret] + } else { + ret[key as keyof typeof ret] = value as DeepOmit< + T, + Fields[number] + >[keyof typeof ret] + } + } + return ret +} + +/** + * @template T + * + * @param field When the type is known to be a record, field is Path or Field; otherwise string + * @param match regular expression or string to match the field/path + */ +type FieldWithMatch = { field: T; match: RegExp | string } +/** + * @template T + * + * When the type is known to be a record, a path, a field or FieldWithMatch + */ +type FieldOptionType< + T, + PF = T extends Record ? Path | Field : string, +> = PF | FieldWithMatch +type ExcludePathsOptionType< + T, + P = T extends Record ? Path : string, +> = Array

+type ExcludeFieldsOptionType< + T, + F = T extends Record ? Field : string, +> = Array + +type StrippedSnapshotOptions = { + /** + * @template T + * Array of fields _not_ to be stripped + */ + excludeFields?: ExcludeFieldsOptionType + /** + * @template T + * Array of paths _not_ to be stripped + */ + excludePaths?: ExcludePathsOptionType + /** + * @template T + * @type {Array | Field>>} + * Array of fields or paths to be used as id fields, ie. matched with a regular expression or exact match + */ + idFields?: Array> // | Array>// IdFieldOptionType +} + +type StrippedSnapshotFinalOptions> = { + excludeFields: Array> + excludePaths: Array> + idFields: Array | Field>> +} + +function isDefinedOrNull(val: T | null): val is T | null { + return typeof val !== "undefined" +} + +const defaultIdFields: Array>> = [ + { + field: "id", + match: ID_REGEX, + }, +] + +const normalizeOptions = >( + options: StrippedSnapshotOptions, +): StrippedSnapshotFinalOptions => { + const { + excludeFields = [], + excludePaths = [], + idFields: _idFields = defaultIdFields, + } = options + + const idFields = _idFields.map((field) => { + if (typeof field === "string") { + return { field, match: ID_REGEX } + } + return field + }) as Array | Field>> + + const _options = { + idFields, + excludeFields: excludeFields as Array>, + excludePaths: excludePaths as Array>, + } + return _options +} + +const pathname = (path: Path, key: keyof T): Path => + (path ? `${String(path)}.${String(key)}` : key) as Path + +function isObjectOrArray( + val: unknown, +): val is Array | Record { + return isObject(val) || Array.isArray(val) +} + +const getIdField = ( + idFields: Array | Field>>, + key: Path | Field, +) => { + return idFields.find((idField) => idField.field === key) +} + +export function idsToExpect< + T extends Record, + U extends { [K in keyof T]: any } = { [K in keyof T]: any }, +>( + obj: T | null, + propertyMatchers: Partial = {}, + options: StrippedSnapshotFinalOptions = {} as StrippedSnapshotFinalOptions, + path = "" as Path, +): Partial { + if (!isObject(obj) || Array.isArray(obj) || isNullOrUndefined(obj)) { + return propertyMatchers + } + + const { excludeFields, excludePaths, idFields } = options + const ret = { ...propertyMatchers } + + for (const key of Object.keys(obj) as Array) { + const currentPath = pathname(path, key) + const value = obj[key] + + if (Array.isArray(value)) { + const expectedArray = getExpectedArray( + value, + ret, + key, + options, + currentPath, + ) + if ( + expectedArray.length > 0 && + (!isObject(expectedArray[0]) || + (isObject(expectedArray[0]) && + expectedArray.every((val: any) => Object.keys(val).length > 0))) + ) { + ret[key] = expectedArray as any + } + } else if (isObject(value)) { + const expectedObject = idsToExpect( + value, + ret[key], + options as StrippedSnapshotFinalOptions, + currentPath as Path, + ) + if (Object.keys(expectedObject).length > 0) { + ret[key] = expectedObject as any + } + } else { + if ( + excludeFields.includes(key as Field) || + excludePaths.includes(path) || + excludePaths.includes(currentPath) + ) { + continue + } + const idFieldKey = getIdField(idFields, key as Field) + const idFieldPath = getIdField(idFields, path) + + if (idFieldKey || (idFieldPath?.match && !isDefinedOrNull(ret[key]))) { + ret[key] = expect.stringMatching( + idFieldKey?.match ?? idFieldPath?.match ?? "", + ) + } + } + } + + return ret +} + +function getExpectedArray< + T extends Record, + U extends { + [K in keyof T]: any + } = { + [K in keyof T]: any + }, +>( + value: T[keyof T] & any[], + ret: Partial, + key: keyof T, + options: StrippedSnapshotFinalOptions, + currentPath: string, +): Array> { + return value.map((val: (typeof value)[number], index: number) => { + const matchers = getArrayMatchers(ret, key, index) + if (!isObjectOrArray(val)) { + return matchers ?? val + } + if (Array.isArray(val)) { + return getExpectedArray( + val as (typeof value)[number][number], + ret, + key, + options, + currentPath, + ) + } + + return idsToExpect(val, matchers, options, currentPath) + }) +} + +function getArrayMatchers>( + ret: Partial, + key: keyof T, + index: number, +) { + return Array.isArray(ret[key]) ? ret[key]?.[index] : ret[key] +} + +type AnyOrArrayAnyObject = T extends Array + ? { [K in keyof R]: any } + : { [K in keyof T]: any } + +/** + * + * @template {T} + * @param {StrippedSnapshotOptions} _options + * @returns + */ +function toMatchStrippedSnapshot< + T, + U extends AnyOrArrayAnyObject = AnyOrArrayAnyObject, + //R extends TypeOrArrayType = TypeOrArrayType, +>( + this: MatcherContext, + actual: T, + propertyMatchers: Partial = {}, + _options: StrippedSnapshotOptions = {} as StrippedSnapshotOptions, +) { + const options = normalizeOptions(_options) + if (Array.isArray(actual)) { + if (!isObject(actual[0])) { + return toMatchSnapshot.call( + this as Context, + actual, + propertyMatchers, + "toMatchStrippedSnapshot", + ) + } + + const strippedActual = actual.map(stripDates) + const expected = actual.map((val) => + idsToExpect(val, propertyMatchers, options), + ) + + return toMatchSnapshot.call( + this as Context, + strippedActual, + expected, + "toMatchStrippedSnapshot", + ) + } + if (isObject(actual)) { + const strippedActual = stripDates(actual) + const expected = idsToExpect( + strippedActual, + propertyMatchers as Record, + options, + ) + + return toMatchSnapshot.call( + this as Context, + strippedActual, + expected, + "toMatchStrippedSnapshot", + ) + } + return toMatchSnapshot.call( + this as Context, + actual, + propertyMatchers, + "toMatchStrippedSnapshot", + ) +} + +expect.extend({ + toMatchStrippedSnapshot, +}) + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace jest { + interface Matchers { + /** + * Match snapshot, but strip all dates (`created_at`, `updated_at`), as well as replacing any specified fields with a regex match. + * Default is to match any `id` field with a Prisma id regex. + * + * @template {T} + * @param propertyMatchers + * @param {StrippedSnapshotOptions} options + * @param {ExcludeFieldsOptionType} options.excludeFields - Fields to _not_ strip. Will match all fields with htis name, regardless of path. + * @param {ExcludePathsOptionType} options.excludePaths - Paths to _not_ strip. Will match only fields that match exactly.. + * @param {Array>} options.idFields - fields to consider as id fields + */ + toMatchStrippedSnapshot< + U extends AnyOrArrayAnyObject = AnyOrArrayAnyObject, + >( + propertyMatchers?: Partial, + options?: StrippedSnapshotOptions, + ): R + } + } +} diff --git a/backend/tests/util/tmc.ts b/backend/tests/util/tmc.ts index a74d0c1ae..2b6170f1a 100644 --- a/backend/tests/util/tmc.ts +++ b/backend/tests/util/tmc.ts @@ -10,7 +10,7 @@ export function fakeTMCCurrent( ) { return { setup() { - nock(TMC_HOST || "") + nock(TMC_HOST ?? "") .persist() .get(url) .reply(function () { @@ -32,7 +32,7 @@ export function fakeTMCSpecific(users: Record) { return { setup() { for (const [user_id, reply] of Object.entries(users)) { - nock(TMC_HOST || "") + nock(TMC_HOST ?? "") .persist() .get(`/api/v8/users/${user_id}?show_user_fields=1&extra_fields=1`) .reply(function () { @@ -50,11 +50,11 @@ export function fakeTMCSpecific(users: Record) { } export const fakeGetAccessToken = (reply: [number, string]) => - nock(TMC_HOST || "") + nock(TMC_HOST ?? "") .post("/oauth/token") .reply(() => [reply[0], { access_token: reply[1] }]) export const fakeUserDetailReply = (reply: [number, object]) => - nock(TMC_HOST || "") + nock(TMC_HOST ?? "") .get("/api/v8/users/recently_changed_user_details") .reply(reply[0], () => reply[1]) diff --git a/backend/tsconfig.json b/backend/tsconfig.json index b5fbb155c..4b178f8db 100644 --- a/backend/tsconfig.json +++ b/backend/tsconfig.json @@ -10,6 +10,7 @@ "module": "commonjs", "outDir": "./dist", "strict": true, + "strictNullChecks": true, "noEmit": true, "noImplicitAny": true, "noImplicitOverride": true, @@ -18,7 +19,7 @@ "noUnusedParameters": true, "skipLibCheck": true, "esModuleInterop": true, - "plugins": [{ "name": "nexus/typescript-language-service" }] + "plugins": [{ "name": "nexus/typescript-language-service" }], // "typeRoots": ["node_modules/@types", "types"] }, "include": [".", "./bin/**/*", "types.d.ts"], diff --git a/backend/tsconfig.production.json b/backend/tsconfig.production.json index d6d27873b..09182c384 100644 --- a/backend/tsconfig.production.json +++ b/backend/tsconfig.production.json @@ -9,6 +9,7 @@ "module": "commonjs", "outDir": "./dist", "strict": true, + "strictNullChecks": true, "noEmit": false, "noImplicitAny": true, "noUnusedLocals": true, diff --git a/backend/util/courseMutationHelpers.ts b/backend/util/courseMutationHelpers.ts new file mode 100644 index 000000000..49dfb8cfb --- /dev/null +++ b/backend/util/courseMutationHelpers.ts @@ -0,0 +1,259 @@ +import { Course, Prisma } from "@prisma/client" + +import { isNotNullOrUndefined } from "./isNullOrUndefined" +import { Context } from "/context" + +export const getIds = (arr: any[], idField = "id") => + (arr || []).map((t) => t[idField]) +const filterNotIncluded = ( + arr1: any[], + arr2: any[], + idField = "id", + mapToId = true, +) => { + const ids1 = getIds(arr1, idField) + const ids2 = getIds(arr2, idField) + + const filtered = ids1.filter((id) => !ids2.includes(id)) + + if (mapToId) { + return filtered.map((id) => ({ [idField]: id })) + } + + return filtered +} + +type IdKeyType = "id" | `${string}_id` + +type PartialAndNullable = { [P in keyof T]?: T[P] | null } + +type InferSelectType> = + Prisma.Prisma__CourseClient[Relation] extends ( + args?: Prisma.Subset | undefined, + ) => any + ? Prisma.Prisma__CourseClient[Relation] extends ( + args?: Prisma.Subset | undefined, + ) => Prisma.CheckSelect + ? S + : never + : never + +// limit to relations of array type +type CourseRelation = { + [Key in keyof Prisma.Prisma__CourseClient]: InferSelectType extends infer S + ? S extends Promise> + ? Key + : never + : never +}[keyof Prisma.Prisma__CourseClient] + +// get relation type from relation name +type CourseRelationType = + InferSelectType extends infer S + ? S extends Promise + ? Type extends Array + ? NonNullable + : NonNullable + : never + : never + +// get any id fields from relation name through relation type +// TODO: actually should be getting composite keys as well, those should be accessible through CourseUpdateInput[Relation] -> where +type CourseRelationKey = { + [Key in keyof CourseRelationType]: Key extends IdKeyType + ? Key + : never +}[keyof CourseRelationType] + +type CreateMutationReturn = + Prisma.CourseUpdateInput[Relation] + +type CreateMutationParams< + Relation extends CourseRelation = CourseRelation, + RelationInstance extends CourseRelationType = CourseRelationType, + IdKey extends CourseRelationKey = CourseRelationKey, +> = IdKey extends IdKeyType + ? { + data?: RelationInstance[] | null + relation: Relation + id?: IdKey + } + : never + +type CourseMutationFunction< + Relation extends CourseRelation, + IdKey extends CourseRelationKey = CourseRelationKey, +> = ( + params: CreateMutationParams, IdKey>, +) => Promise> + +// - given the data (a course field like course_translations) and the field name, returns the Prisma mutations to create, update, or delete data +const createCourseMutationFunction = + < + Relation extends CourseRelation = CourseRelation, + IdKey extends CourseRelationKey = CourseRelationKey, + >( + ctx: Context, + slug: string, + ): CourseMutationFunction => + /*async < + Relation extends CourseRelation, + // RelationInstance extends CourseRelationType = CourseRelationType, + IdKey extends CourseRelationKey = CourseRelationKey, + >*/ async ( + { data, relation, id = "id" as IdKey } /*: CreateMutationParams*/, + ) => { + /*: Promise< + CreateMutationReturn + > => {*/ + if (!isNotNullOrUndefined(data)) { + return undefined + } + + let existing + + try { + // @ts-ignore: can't be arsed to do the typing, works + existing = await ctx.prisma.course + .findUnique({ where: { slug } }) + [relation]() + } catch (e) { + throw new Error( + `error creating mutation ${String(relation)} for course ${slug}: ${e}`, + ) + } + + const hasIdFilter = hasId(id as IdKey) + const hasNotIdFilter = hasNotId(id as IdKey) + + const mutation = {} as NonNullable> //CreateMutationReturn + mutation.create = data + .filter(hasNotIdFilter) // (t) => !t.id + .map((t) => Object.assign({}, t, { [id]: undefined })) + mutation.updateMany = data + .filter(isNotNullOrUndefined) + .filter(hasIdFilter) // (t) => !!t.id) + .map((t) => { + return { + where: { [id]: t[id as IdKey] }, + data: t, //{ ...t, id: undefined }, + } + }) + mutation.deleteMany = filterNotIncluded(existing ?? [], data, id) + + return mutation + } + +type MutableRelationWithId = + Relation extends CourseRelation + ? { name: Relation; id: CourseRelationKey & string } + : never +type MutableRelation = + | Relation + | MutableRelationWithId + +type CourseMutationsReturn = { + [Key in Relations[number]]: CreateMutationReturn | undefined +} + +const isMutableRelationWithId = < + Relation extends CourseRelation = CourseRelation, +>( + relation: MutableRelation, +): relation is MutableRelationWithId => + typeof relation === "object" && "name" in relation && "id" in relation + +type CourseRelationsFromMutableRelations< + MutableRelations extends readonly MutableRelation[], +> = { + [K in keyof MutableRelations]: MutableRelations[K] extends MutableRelationWithId< + infer Relation + > + ? Relation + : MutableRelations[K] +}[number] & + readonly CourseRelation[] + +type DataType = PartialAndNullable & { + [Key in CourseRelation]?: Array< + PartialAndNullable> + > | null +} + +// - fields are course related fields, which can be either given in string form or as an object with name and id, if the object id is something else than "id" +// - returns mutations to create, update, or delete data +export const createCourseMutations = + (ctx: Context, slug: string) => + < + MutableRelations extends readonly MutableRelation[] = readonly MutableRelation[], + Relations extends CourseRelationsFromMutableRelations = CourseRelationsFromMutableRelations, + >( + relations: MutableRelations, + ) => + async (data: DataType) => { + const mutations = {} as CourseMutationsReturn + const courseMutationFunction = createCourseMutationFunction< + Relations[number] + >(ctx, slug) + + for (const relation of relations) { + if (isMutableRelationWithId(relation)) { + mutations[relation.name as Relations[number]] = + await courseMutationFunction({ + data: data[relation.name], + relation: relation.name, + id: relation.id, + } as CreateMutationParams) + } else { + mutations[relation as Relations[number]] = await courseMutationFunction( + { data: data[relation], relation } as CreateMutationParams< + Relations[number] + >, + ) + } + } + + return mutations + } + +export const connectOrDisconnect = ( + receivedArg: string | null | undefined, + existing: T | null, +) => { + if (receivedArg) { + return { connect: { id: receivedArg } } + } + if (existing) { + return { disconnect: true } + } + + return undefined +} + +const hasId = + < + Relation extends CourseRelation = CourseRelation, + IdKey extends CourseRelationKey = CourseRelationKey, + >( + id: IdKey, + ) => + < + RelationInstance extends CourseRelationType = CourseRelationType, + >( + data: any, + ): data is RelationInstance & { [key in IdKey]: string | null } => + Boolean(data?.[id]) + +const hasNotId = + < + Relation extends CourseRelation = CourseRelation, + IdKey extends CourseRelationKey = CourseRelationKey, + >( + id: IdKey, + ) => + < + RelationInstance extends CourseRelationType = CourseRelationType, + >( + data: any, + ): data is RelationInstance & { [key in IdKey]: undefined } => + !Boolean(data?.[id]) diff --git a/backend/util/db-functions.ts b/backend/util/db-functions.ts index 73d81d2c7..2eff538ce 100644 --- a/backend/util/db-functions.ts +++ b/backend/util/db-functions.ts @@ -110,102 +110,87 @@ interface ConvertPaginationOutput { } export const convertPagination = ( - { first, last, before, after, skip }: ConvertPaginationInput, + { first, last, before, after, skip: skipValue }: ConvertPaginationInput, options?: ConvertPaginationOptions, ): ConvertPaginationOutput => { - const skipValue = skip || 0 - const { field = "id" } = options || {} + const { field = "id" } = options ?? {} if (!first && !last) { throw new Error("first or last must be defined") } + let skip = skipValue ?? 0 + let take = 0 + let cursor = undefined + + if (notEmpty(before)) { + skip += 1 + cursor = { [field]: before } + } else if (notEmpty(after)) { + cursor = { [field]: after } + } + if (notEmpty(last)) { + take = -(last ?? 0) + } else if (notEmpty(first)) { + take = first + } + return { - skip: notEmpty(before) ? skipValue + 1 : skipValue, - take: notEmpty(last) ? -(last ?? 0) : notEmpty(first) ? first : 0, - cursor: notEmpty(before) - ? { [field]: before } - : notEmpty(after) - ? { [field]: after } - : undefined, + skip, + take, + cursor, } } -export const filterNull = >( +type NullFiltered = T extends null + ? Exclude + : T extends Array + ? Array> + : T extends Record + ? { + [K in keyof T]: NullFiltered + } + : T + +export const filterNull = >( o?: T | null, -): T | undefined => +): NullFiltered | undefined => o ? (Object.fromEntries( Object.entries(o).map(([k, v]) => [k, v === null ? undefined : v]), - ) as T) + ) as NullFiltered) : undefined -// convertUpdate not needed anymore, hopefully -/*type ObjectEntries = { - [K in keyof T]: [K, T[K]] -}[keyof T][] - -type ConvertedUpdate = T extends Array - ? U extends { [key: string]: any } - ? Array> - : U extends Array - ? Array> - : Array - : T extends NonNullable<{ [key: string]: any }> - ? T extends Date - ? T - : { [K in keyof T]: - K extends string & "disconnect" | "skipDuplicates" | "order" - ? T[K] - : ConvertedUpdate } - : T extends number - ? { set: number } | undefined - : T extends boolean - ? { set: boolean } - : T - -const isObject = (o: T): o is T & { [key: string]: any } => - o !== null && typeof o === "object" +export const filterNullRecursive = < + T extends Record, +>( + o?: T | null, +): NullFiltered | undefined => { + if (!o) { + return undefined + } + const filtered = filterNull(o) -// helper function to convert to atomicNumberOperations -// https://github.com/prisma/prisma/issues/3491#issuecomment-689542237 -export function convertUpdate( - input: T, -): ConvertedUpdate { - if (!isObject(input)) { - return input + if (!filtered) { + return undefined } - const result = {} as Record - - for (const [key, value] of Object.entries(input) as ObjectEntries) { - if (Array.isArray(value)) { - result[key] = value.map(convertUpdate) - } else if ( - typeof value === "object" && - value !== null && - !((value as object) instanceof Date) - ) { - result[key] = convertUpdate(value) - } else if (typeof value === "number") { - if (Number.isNaN(value)) { - result[key] = undefined - } else { - result[key] = { set: value } + return Object.fromEntries( + Object.entries(filtered).map(([k, v]) => { + if (Array.isArray(v)) { + return [k, v.map(filterNullRecursive)] } - } else if (typeof value === "boolean") { - if (key === "disconnect" || key === "skipDuplicates") { - result[key] = value - } else { - result[key] = { set: value } + if (typeof v === "object" && v !== null) { + return [ + k, + filterNullRecursive(v as Record), + ] } - } else { - result[key] = value - } - } - return result as ConvertedUpdate -}*/ + return [k, v === null ? undefined : v] + }), + ) as NullFiltered +} export const createExtensions = async (knex: Knex) => { /*if (CIRCLECI) { @@ -284,8 +269,61 @@ export const getCourseOrAliasKnex = type InferPrismaClientGlobalReject = C extends PrismaClient ? GlobalReject : never -type FindUniqueCourseType = - Prisma.CourseDelegate>["findUnique"] +type FindUniqueFunction< + T extends Prisma.CourseFindUniqueArgs, + _LocalRejectSettings = T["rejectOnNotFound"] extends Prisma.RejectOnNotFound + ? T["rejectOnNotFound"] + : undefined, +> = <_, _LocalRejectSettings>( + args: Prisma.SelectSubset, +) => any +type FindUniqueSelectType< + T extends Prisma.CourseFindUniqueArgs, + RejectOnNotFound = any, +> = RejectOnNotFound extends Prisma.True + ? Prisma.CheckSelect< + T, + Prisma.Prisma__CourseClient, + Prisma.Prisma__CourseClient> + > + : Prisma.CheckSelect< + T, + Prisma.Prisma__CourseClient, + Prisma.Prisma__CourseClient | null> + > + +// @ts-ignore: not used +type FindUniqueCourseType< + ClientType extends PrismaClient, + T extends Prisma.CourseFindUniqueArgs, +> = { + [K in keyof Prisma.CourseDelegate< + InferPrismaClientGlobalReject + >]: K extends "findUnique" + ? Prisma.CourseDelegate< + InferPrismaClientGlobalReject + >[K] extends ( + args: Prisma.SelectSubset, + ) => infer U + ? (args: Prisma.SelectSubset) => U + : never + : never +}[keyof Prisma.CourseDelegate>] + +type FindUniqueCourseReturnType< + ClientType extends PrismaClient, + T extends Prisma.CourseFindUniqueArgs, +> = { + [K in keyof Prisma.CourseDelegate< + InferPrismaClientGlobalReject + >]: K extends "findUnique" + ? Prisma.CourseDelegate< + InferPrismaClientGlobalReject + >[K] extends FindUniqueFunction + ? FindUniqueSelectType + : never + : never +}[keyof Prisma.CourseDelegate>] /** * Get course by id or slug, or course_alias course_code provided by slug. @@ -293,10 +331,20 @@ type FindUniqueCourseType = * If slug is given, we also try to find a `course_alias` with that `course_code`. * Course found with slug is preferred to course found with course_code. */ -export const getCourseOrAlias = ( - ctx: BaseContext, -) => - ((args: Prisma.SelectSubset) => { +const checkSelect = ( + args: any, +): args is T & Prisma.SelectAndInclude => { + if (args.select && args.include) { + return true + } + return false +} +// Prisma.CheckSelect, Prisma.Prisma__CourseClient>> { +export const getCourseOrAlias = + (ctx: BaseContext) => + async ( + args: Prisma.SelectSubset, + ): Promise> => { const { id, slug } = args?.where ?? {} const { select, include } = args ?? {} @@ -304,29 +352,23 @@ export const getCourseOrAlias = ( throw new UserInputError("You must provide either an id or a slug") } - if (include && select) { + if (checkSelect(args)) { throw new UserInputError("Only provide one of include or select") } - if (id) { - return ctx.prisma.course.findUnique({ - where: { - id, - slug: slug ?? undefined, - }, - ...omit(args, "where"), - }) - } - - const course = ctx.prisma.course.findUnique({ + const course = await ctx.prisma.course.findUnique({ where: { - slug, + id: id ?? undefined, + slug: slug ?? undefined, }, ...omit(args, "where"), }) if (course) { - return course + return course as unknown as FindUniqueCourseReturnType< + (typeof ctx)["prisma"], + T + > } const selectOrInclude: { @@ -344,8 +386,8 @@ export const getCourseOrAlias = ( ...selectOrInclude, }) - return alias - }) as FindUniqueCourseType + return alias as FindUniqueCourseReturnType<(typeof ctx)["prisma"], T> + } // we're telling TS that this is a course findUnique when in reality // it isn't strictly speaking. But it's close enough for our purposes // to get the type inference we want. diff --git a/backend/util/isNullOrUndefined.ts b/backend/util/isNullOrUndefined.ts index 98e035f1c..4e5fe8927 100644 --- a/backend/util/isNullOrUndefined.ts +++ b/backend/util/isNullOrUndefined.ts @@ -3,3 +3,17 @@ export function isNullOrUndefined( ): obj is null | undefined { return typeof obj === "undefined" || obj === null } + +export function isNotNullOrUndefined(obj: T | null | undefined): obj is T { + return !isNullOrUndefined(obj) +} + +export function fieldIsNotNullOrUndefined< + T extends object, + Field extends keyof T, +>( + obj: T | null | undefined, + field: Field, +): obj is T & { [key in Field]-?: NonNullable } { + return !isNullOrUndefined(obj) && !isNullOrUndefined(obj[field]) +} diff --git a/backend/util/sendMail.ts b/backend/util/sendMail.ts index 240f4dac9..a2bb9ba14 100644 --- a/backend/util/sendMail.ts +++ b/backend/util/sendMail.ts @@ -31,11 +31,11 @@ export async function sendMail( { to, text, subject, html }: SendMailOptions, context?: SendMailContext, ) { - const { logger } = context || {} + const { logger } = context ?? {} const options: SMTPTransport.Options = { host: SMTP_HOST, - port: parseInt(SMTP_PORT || ""), + port: parseInt(SMTP_PORT ?? ""), secure: false, // true for 465, false for other ports auth: { user: SMTP_USER, // generated ethereal user @@ -52,6 +52,6 @@ export async function sendMail( text, // plain text body html, // html body }) - ;(logger?.info || console.log)(`Message sent: ${info.messageId}`) + ;(logger?.info ?? console.log)(`Message sent: ${info.messageId}`) // Message sent: } diff --git a/frontend/components/CreateEmailTemplateDialog.tsx b/frontend/components/CreateEmailTemplateDialog.tsx index 0d32cb2f1..409322f3e 100644 --- a/frontend/components/CreateEmailTemplateDialog.tsx +++ b/frontend/components/CreateEmailTemplateDialog.tsx @@ -1,4 +1,4 @@ -import { useState } from "react" +import { useMemo, useState } from "react" import { omit } from "lodash" import Router from "next/router" @@ -18,6 +18,7 @@ import { import CustomSnackbar from "/components/CustomSnackbar" import Spinner from "/components/Spinner" +import notEmpty from "/util/notEmpty" import { AddEmailTemplateDocument, @@ -47,14 +48,6 @@ const CreateEmailTemplateDialog = ({ const { loading, error, data } = useQuery(EmailTemplateEditorCoursesDocument) const client = useApolloClient() - if (loading) { - return - } - //TODO fix error messages - if (error || !data) { - return

Error has occurred

- } - const handleDialogClickOpen = () => { setOpenDialog(true) } @@ -63,24 +56,32 @@ const CreateEmailTemplateDialog = ({ setOpenDialog(false) } - const courseOptions = - templateType === "completion" - ? data?.courses + const courseOptions = useMemo(() => { + if (!data) { + return [] + } + + if (templateType === "completion") { + return ( + data.courses + ?.filter(notEmpty) ?.filter((c) => c?.completion_email === null) - .map((c, i) => { - return ( - - ) - }) - : data?.courses?.map((c, i) => { - return ( - - ) - }) + )) ?? [] + ) + } + + return ( + data.courses?.filter(notEmpty)?.map((c, i) => ( + + )) ?? [] + ) + }, [templateType, data]) const handleCreate = async () => { try { @@ -131,6 +132,14 @@ const CreateEmailTemplateDialog = ({ } } + if (loading) { + return + } + //TODO fix error messages + if (error || !data) { + return

Error has occurred

+ } + return (
)} - + diff --git a/frontend/graphql/fragments/course.fragments.graphql b/frontend/graphql/fragments/course.fragments.graphql index cd189aa37..dda507bd7 100644 --- a/frontend/graphql/fragments/course.fragments.graphql +++ b/frontend/graphql/fragments/course.fragments.graphql @@ -30,6 +30,12 @@ fragment CourseTranslationDetailedFields on CourseTranslation { updated_at } +fragment CourseTagFields on CourseTag { + tag { + ...TagCoreFields + } +} + fragment CourseFields on Course { ...CourseWithPhotoCoreFields description @@ -55,6 +61,9 @@ fragment CourseFields on Course { study_modules { ...StudyModuleCoreFields } + tags { + ...TagCoreFields + } } fragment EditorCourseFields on Course { @@ -77,6 +86,9 @@ fragment EditorCourseFields on Course { id language } + tags { + ...TagCoreFields + } } fragment EditorCourseDetailedFields on Course { diff --git a/frontend/graphql/fragments/tag.fragments.graphql b/frontend/graphql/fragments/tag.fragments.graphql new file mode 100644 index 000000000..d1990558a --- /dev/null +++ b/frontend/graphql/fragments/tag.fragments.graphql @@ -0,0 +1,16 @@ +fragment TagCoreFields on Tag { + id + hidden + types + name + tag_translations { + ...TagTranslationFields + } +} + +fragment TagTranslationFields on TagTranslation { + tag_id + name + description + language +} \ No newline at end of file diff --git a/frontend/graphql/generated/index.ts b/frontend/graphql/generated/index.ts index d34bab765..5f1d0ad08 100644 --- a/frontend/graphql/generated/index.ts +++ b/frontend/graphql/generated/index.ts @@ -2,7 +2,6 @@ * This is an automatically generated file. * Run `npm run graphql-codegen` to regenerate. **/ - import { TypedDocumentNode as DocumentNode } from "@graphql-typed-document-node/core" export type Maybe = T | null @@ -16,7 +15,7 @@ export type MakeOptional = Omit & { export type MakeMaybe = Omit & { [SubKey in K]: Maybe } -// Generated on 2023-01-13T16:44:49+02:00 +// Generated on 2023-01-19T20:19:31+02:00 /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { @@ -51,6 +50,11 @@ export type AbEnrollmentCreateOrUpsertInput = { user_id: Scalars["ID"] } +export type AbEnrollmentOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type AbEnrollmentUser_idAb_study_idCompoundUniqueInput = { ab_study_id: Scalars["String"] user_id: Scalars["String"] @@ -142,6 +146,11 @@ export type CompletionEdge = { node: Completion } +export type CompletionOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type CompletionRegistered = { __typename?: "CompletionRegistered" completion: Maybe @@ -159,6 +168,11 @@ export type CompletionRegistered = { user_id: Maybe } +export type CompletionRegisteredOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type CompletionRegisteredWhereUniqueInput = { id?: InputMaybe } @@ -210,6 +224,7 @@ export type Course = { study_module_start_point: Maybe study_modules: Array support_email: Maybe + tags: Array teacher_in_charge_email: Scalars["String"] teacher_in_charge_name: Scalars["String"] tier: Maybe @@ -276,6 +291,13 @@ export type Coursestudy_modulesArgs = { take?: InputMaybe } +export type CoursetagsArgs = { + includeHidden?: InputMaybe + language?: InputMaybe + search?: InputMaybe + types?: InputMaybe> +} + export type Courseuser_course_settings_visibilitiesArgs = { cursor?: InputMaybe skip?: InputMaybe @@ -297,6 +319,11 @@ export type CourseAliasCreateInput = { course_code: Scalars["String"] } +export type CourseAliasOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type CourseAliasUpsertInput = { course?: InputMaybe course_code: Scalars["String"] @@ -341,6 +368,7 @@ export type CourseCreateArg = { study_module_start_point?: InputMaybe study_modules?: InputMaybe> support_email?: InputMaybe + tags?: InputMaybe> teacher_in_charge_email: Scalars["String"] teacher_in_charge_name: Scalars["String"] tier?: InputMaybe @@ -351,37 +379,87 @@ export type CourseCreateArg = { } export type CourseOrderByInput = { + created_at?: InputMaybe + ects?: InputMaybe + end_date?: InputMaybe + exercise_completions_needed?: InputMaybe + id?: InputMaybe + name?: InputMaybe + order?: InputMaybe + points_needed?: InputMaybe + slug?: InputMaybe + start_date?: InputMaybe + study_module_order?: InputMaybe + support_email?: InputMaybe + teacher_in_charge_email?: InputMaybe + teacher_in_charge_name?: InputMaybe + tier?: InputMaybe + updated_at?: InputMaybe +} + +export type CourseOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + +export type CourseOrderByWithRelationInput = { automatic_completions?: InputMaybe automatic_completions_eligible_for_ects?: InputMaybe + completion_email?: InputMaybe completion_email_id?: InputMaybe + completions?: InputMaybe + completions_handled_by?: InputMaybe completions_handled_by_id?: InputMaybe + completions_registered?: InputMaybe + course_aliases?: InputMaybe + course_organizations?: InputMaybe + course_stats_email?: InputMaybe course_stats_email_id?: InputMaybe + course_tags?: InputMaybe + course_translations?: InputMaybe + course_variants?: InputMaybe created_at?: InputMaybe ects?: InputMaybe end_date?: InputMaybe exercise_completions_needed?: InputMaybe + exercises?: InputMaybe + handles_completions_for?: InputMaybe has_certificate?: InputMaybe hidden?: InputMaybe id?: InputMaybe + inherit_settings_from?: InputMaybe inherit_settings_from_id?: InputMaybe name?: InputMaybe + open_university_registration_links?: InputMaybe order?: InputMaybe + other_course_courseTocourse_inherit_settings_from?: InputMaybe + owner_organization?: InputMaybe owner_organization_id?: InputMaybe + ownerships?: InputMaybe + photo?: InputMaybe photo_id?: InputMaybe points_needed?: InputMaybe promote?: InputMaybe + services?: InputMaybe slug?: InputMaybe start_date?: InputMaybe start_point?: InputMaybe status?: InputMaybe + stored_data?: InputMaybe study_module_order?: InputMaybe study_module_start_point?: InputMaybe + study_modules?: InputMaybe support_email?: InputMaybe teacher_in_charge_email?: InputMaybe teacher_in_charge_name?: InputMaybe tier?: InputMaybe + triggered_automatically_email?: InputMaybe upcoming_active_link?: InputMaybe updated_at?: InputMaybe + user_course_progresses?: InputMaybe + user_course_service_progresses?: InputMaybe + user_course_settings?: InputMaybe + user_course_settings_visibilities?: InputMaybe } export type CourseOrganization = { @@ -396,6 +474,11 @@ export type CourseOrganization = { updated_at: Maybe } +export type CourseOrganizationOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type CourseOrganizationWhereUniqueInput = { id?: InputMaybe } @@ -411,6 +494,11 @@ export type CourseOwnership = { user_id: Maybe } +export type CourseOwnershipOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type CourseOwnershipUser_idCourse_idCompoundUniqueInput = { course_id: Scalars["String"] user_id: Scalars["String"] @@ -432,6 +520,11 @@ export type CourseStatsSubscription = { user_id: Maybe } +export type CourseStatsSubscriptionOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type CourseStatsSubscriptionUser_idEmail_template_idCompoundUniqueInput = { email_template_id: Scalars["String"] @@ -449,6 +542,42 @@ export enum CourseStatus { Upcoming = "Upcoming", } +export type CourseTag = { + __typename?: "CourseTag" + course: Course + course_id: Scalars["String"] + created_at: Maybe + language: Maybe + tag: Maybe + tag_id: Scalars["String"] + updated_at: Maybe +} + +export type CourseTagCourse_idTag_idCompoundUniqueInput = { + course_id: Scalars["String"] + tag_id: Scalars["String"] +} + +export type CourseTagCreateOrUpsertInput = { + course_id: Scalars["ID"] + tag?: InputMaybe + tag_id: Scalars["ID"] +} + +export type CourseTagCreateOrUpsertWithoutCourseIdInput = { + tag?: InputMaybe + tag_id: Scalars["ID"] +} + +export type CourseTagOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + +export type CourseTagWhereUniqueInput = { + course_id_tag_id?: InputMaybe +} + export type CourseTranslation = { __typename?: "CourseTranslation" course: Maybe @@ -472,6 +601,11 @@ export type CourseTranslationCreateInput = { name: Scalars["String"] } +export type CourseTranslationOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type CourseTranslationUpsertInput = { course?: InputMaybe description: Scalars["String"] @@ -522,6 +656,7 @@ export type CourseUpsertArg = { study_module_start_point?: InputMaybe study_modules?: InputMaybe> support_email?: InputMaybe + tags?: InputMaybe> teacher_in_charge_email: Scalars["String"] teacher_in_charge_name: Scalars["String"] tier?: InputMaybe @@ -549,6 +684,11 @@ export type CourseVariantCreateInput = { slug: Scalars["String"] } +export type CourseVariantOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type CourseVariantUpsertInput = { course?: InputMaybe description?: InputMaybe @@ -580,6 +720,11 @@ export type EmailDelivery = { user_id: Maybe } +export type EmailDeliveryOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type EmailDeliveryWhereUniqueInput = { id?: InputMaybe } @@ -621,6 +766,31 @@ export type EmailTemplateemail_deliveriesArgs = { take?: InputMaybe } +export type EmailTemplateOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + +export type EmailTemplateOrderByWithRelationInput = { + course_instance_language?: InputMaybe + course_stats_subscriptions?: InputMaybe + courses?: InputMaybe + created_at?: InputMaybe + email_deliveries?: InputMaybe + exercise_completions_threshold?: InputMaybe + html_body?: InputMaybe + id?: InputMaybe + name?: InputMaybe + points_threshold?: InputMaybe + stats_courses?: InputMaybe + template_type?: InputMaybe + title?: InputMaybe + triggered_automatically_by_course?: InputMaybe + triggered_automatically_by_course_id?: InputMaybe + txt_body?: InputMaybe + updated_at?: InputMaybe +} + export type Exercise = { __typename?: "Exercise" course: Maybe @@ -641,7 +811,7 @@ export type Exercise = { } export type Exerciseexercise_completionsArgs = { - orderBy?: InputMaybe + orderBy?: InputMaybe user_id?: InputMaybe } @@ -668,15 +838,33 @@ export type ExerciseCompletionexercise_completion_required_actionsArgs = { } export type ExerciseCompletionOrderByInput = { + created_at?: InputMaybe + exercise_id?: InputMaybe + id?: InputMaybe + n_points?: InputMaybe + timestamp?: InputMaybe + updated_at?: InputMaybe + user_id?: InputMaybe +} + +export type ExerciseCompletionOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + +export type ExerciseCompletionOrderByWithRelationInput = { attempted?: InputMaybe completed?: InputMaybe created_at?: InputMaybe + exercise?: InputMaybe + exercise_completion_required_actions?: InputMaybe exercise_id?: InputMaybe id?: InputMaybe n_points?: InputMaybe original_submission_date?: InputMaybe timestamp?: InputMaybe updated_at?: InputMaybe + user?: InputMaybe user_id?: InputMaybe } @@ -688,6 +876,11 @@ export type ExerciseCompletionRequiredAction = { value: Scalars["String"] } +export type ExerciseCompletionRequiredActionOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type ExerciseCompletionRequiredActionWhereUniqueInput = { id?: InputMaybe } @@ -696,6 +889,29 @@ export type ExerciseCompletionWhereUniqueInput = { id?: InputMaybe } +export type ExerciseOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + +export type ExerciseOrderByWithRelationInput = { + course?: InputMaybe + course_id?: InputMaybe + created_at?: InputMaybe + custom_id?: InputMaybe + deleted?: InputMaybe + exercise_completions?: InputMaybe + id?: InputMaybe + max_points?: InputMaybe + name?: InputMaybe + part?: InputMaybe + section?: InputMaybe + service?: InputMaybe + service_id?: InputMaybe + timestamp?: InputMaybe + updated_at?: InputMaybe +} + export type ExerciseProgress = { __typename?: "ExerciseProgress" exercise_count: Maybe @@ -724,6 +940,22 @@ export type Image = { updated_at: Maybe } +export type ImageOrderByWithRelationInput = { + compressed?: InputMaybe + compressed_mimetype?: InputMaybe + courses?: InputMaybe + created_at?: InputMaybe + default?: InputMaybe + encoding?: InputMaybe + id?: InputMaybe + name?: InputMaybe + original?: InputMaybe + original_mimetype?: InputMaybe + uncompressed?: InputMaybe + uncompressed_mimetype?: InputMaybe + updated_at?: InputMaybe +} + export type ManualCompletionArg = { completion_date?: InputMaybe grade?: InputMaybe @@ -739,6 +971,7 @@ export type Mutation = { addCourse: Maybe addCourseAlias: Maybe addCourseOrganization: Maybe + addCourseTag: CourseTag addCourseTranslation: Maybe addCourseVariant: Maybe addEmailTemplate: Maybe @@ -758,15 +991,22 @@ export type Mutation = { addVerifiedUser: Maybe createCourseStatsSubscription: Maybe createRegistrationAttemptDate: Maybe + createTag: Maybe + createTagTranslation: Maybe + createTagType: Maybe deleteCourse: Maybe deleteCourseOrganization: Maybe deleteCourseStatsSubscription: Maybe + deleteCourseTag: CourseTag deleteCourseTranslation: Maybe deleteCourseVariant: Maybe deleteEmailTemplate: Maybe deleteImage: Maybe deleteStudyModule: Maybe deleteStudyModuleTranslation: Maybe + deleteTag: Maybe + deleteTagTranslation: Maybe + deleteTagType: Maybe deleteUserOrganization: Maybe recheckCompletions: Maybe registerCompletion: Scalars["String"] @@ -781,6 +1021,9 @@ export type Mutation = { updateService: Maybe updateStudyModule: Maybe updateStudyModuletranslation: Maybe + updateTag: Maybe + updateTagTranslation: Maybe + updateTagType: Maybe updateUserName: Maybe updateUserOrganization: Maybe } @@ -818,6 +1061,13 @@ export type MutationaddCourseOrganizationArgs = { organization_id: Scalars["ID"] } +export type MutationaddCourseTagArgs = { + course_id?: InputMaybe + course_slug?: InputMaybe + tag_id?: InputMaybe + tag_name?: InputMaybe +} + export type MutationaddCourseTranslationArgs = { course?: InputMaybe description?: InputMaybe @@ -869,7 +1119,7 @@ export type MutationaddImageArgs = { } export type MutationaddManualCompletionArgs = { - completions?: InputMaybe>> + completions?: InputMaybe> course_id: Scalars["String"] } @@ -938,6 +1188,23 @@ export type MutationcreateRegistrationAttemptDateArgs = { id: Scalars["ID"] } +export type MutationcreateTagArgs = { + hidden?: InputMaybe + translations?: InputMaybe> + types?: InputMaybe> +} + +export type MutationcreateTagTranslationArgs = { + description?: InputMaybe + language: Scalars["String"] + name: Scalars["String"] + tag_id: Scalars["ID"] +} + +export type MutationcreateTagTypeArgs = { + name: Scalars["String"] +} + export type MutationdeleteCourseArgs = { id?: InputMaybe slug?: InputMaybe @@ -951,6 +1218,11 @@ export type MutationdeleteCourseStatsSubscriptionArgs = { id: Scalars["ID"] } +export type MutationdeleteCourseTagArgs = { + course_id: Scalars["ID"] + tag_id: Scalars["ID"] +} + export type MutationdeleteCourseTranslationArgs = { id: Scalars["ID"] } @@ -976,6 +1248,19 @@ export type MutationdeleteStudyModuleTranslationArgs = { id: Scalars["ID"] } +export type MutationdeleteTagArgs = { + id: Scalars["ID"] +} + +export type MutationdeleteTagTranslationArgs = { + language: Scalars["String"] + tag_id: Scalars["ID"] +} + +export type MutationdeleteTagTypeArgs = { + name: Scalars["String"] +} + export type MutationdeleteUserOrganizationArgs = { id: Scalars["ID"] } @@ -1060,6 +1345,24 @@ export type MutationupdateStudyModuletranslationArgs = { study_module: Scalars["ID"] } +export type MutationupdateTagArgs = { + hidden?: InputMaybe + id: Scalars["ID"] + translations?: InputMaybe> + types?: InputMaybe> +} + +export type MutationupdateTagTranslationArgs = { + description?: InputMaybe + language: Scalars["String"] + name: Scalars["String"] + tag_id: Scalars["ID"] +} + +export type MutationupdateTagTypeArgs = { + name: Scalars["String"] +} + export type MutationupdateUserNameArgs = { first_name?: InputMaybe last_name?: InputMaybe @@ -1095,7 +1398,7 @@ export type OpenUniversityRegistrationLink = { link: Maybe start_date: Maybe stop_date: Maybe - tiers: Maybe + tiers: Array updated_at: Maybe } @@ -1105,7 +1408,12 @@ export type OpenUniversityRegistrationLinkCreateInput = { link?: InputMaybe start_date?: InputMaybe stop_date?: InputMaybe - tiers?: InputMaybe + tiers?: InputMaybe> +} + +export type OpenUniversityRegistrationLinkOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe } export type OpenUniversityRegistrationLinkUpsertInput = { @@ -1115,7 +1423,7 @@ export type OpenUniversityRegistrationLinkUpsertInput = { link?: InputMaybe start_date?: InputMaybe stop_date?: InputMaybe - tiers?: InputMaybe + tiers?: InputMaybe> } export type OpenUniversityRegistrationLinkWhereUniqueInput = { @@ -1192,6 +1500,28 @@ export type Organizationverified_usersArgs = { export type OrganizationOrderByInput = { contact_information?: InputMaybe created_at?: InputMaybe + email?: InputMaybe + id?: InputMaybe + phone?: InputMaybe + slug?: InputMaybe + tmc_created_at?: InputMaybe + tmc_updated_at?: InputMaybe + updated_at?: InputMaybe + website?: InputMaybe +} + +export type OrganizationOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + +export type OrganizationOrderByWithRelationInput = { + completions_registered?: InputMaybe + contact_information?: InputMaybe + course_organizations?: InputMaybe + courses?: InputMaybe + created_at?: InputMaybe + creator?: InputMaybe creator_id?: InputMaybe disabled?: InputMaybe email?: InputMaybe @@ -1201,6 +1531,7 @@ export type OrganizationOrderByInput = { logo_file_name?: InputMaybe logo_file_size?: InputMaybe logo_updated_at?: InputMaybe + organization_translations?: InputMaybe phone?: InputMaybe pinned?: InputMaybe secret_key?: InputMaybe @@ -1208,8 +1539,10 @@ export type OrganizationOrderByInput = { tmc_created_at?: InputMaybe tmc_updated_at?: InputMaybe updated_at?: InputMaybe + user_organizations?: InputMaybe verified?: InputMaybe verified_at?: InputMaybe + verified_users?: InputMaybe website?: InputMaybe } @@ -1232,6 +1565,11 @@ export type OrganizationTranslation = { updated_at: Maybe } +export type OrganizationTranslationOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type OrganizationTranslationWhereUniqueInput = { id?: InputMaybe } @@ -1278,6 +1616,7 @@ export type Query = { course: Maybe courseAliases: Array courseOrganizations: Maybe> + courseTags: Maybe> courseTranslations: Maybe> courseVariant: Maybe courseVariants: Maybe> @@ -1302,6 +1641,8 @@ export type Query = { study_module: Maybe study_module_exists: Maybe study_modules: Maybe> + tagTypes: Maybe> + tags: Maybe> user: Maybe userCourseProgress: Maybe userCourseProgresses: Maybe> @@ -1364,6 +1705,15 @@ export type QuerycourseOrganizationsArgs = { organization_id?: InputMaybe } +export type QuerycourseTagsArgs = { + course_id?: InputMaybe + course_slug?: InputMaybe + includeHidden?: InputMaybe + language?: InputMaybe + tag_id?: InputMaybe + tag_types?: InputMaybe> +} + export type QuerycourseTranslationsArgs = { language?: InputMaybe } @@ -1384,9 +1734,11 @@ export type QuerycoursesArgs = { handledBy?: InputMaybe hidden?: InputMaybe language?: InputMaybe - orderBy?: InputMaybe + orderBy?: InputMaybe search?: InputMaybe status?: InputMaybe> + tag_types?: InputMaybe> + tags?: InputMaybe> } export type QuerycurrentUserArgs = { @@ -1407,7 +1759,7 @@ export type QueryexerciseCompletionArgs = { export type QueryexerciseCompletionsArgs = { cursor?: InputMaybe - orderBy?: InputMaybe> + orderBy?: InputMaybe> skip?: InputMaybe take?: InputMaybe } @@ -1436,7 +1788,7 @@ export type QueryorganizationArgs = { export type QueryorganizationsArgs = { cursor?: InputMaybe hidden?: InputMaybe - orderBy?: InputMaybe + orderBy?: InputMaybe skip?: InputMaybe take?: InputMaybe } @@ -1465,7 +1817,13 @@ export type Querystudy_module_existsArgs = { export type Querystudy_modulesArgs = { language?: InputMaybe - orderBy?: InputMaybe + orderBy?: InputMaybe +} + +export type QuerytagsArgs = { + includeHidden?: InputMaybe + language?: InputMaybe + search?: InputMaybe } export type QueryuserArgs = { @@ -1615,6 +1973,22 @@ export type Serviceuser_course_service_progressesArgs = { take?: InputMaybe } +export type ServiceOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + +export type ServiceOrderByWithRelationInput = { + courses?: InputMaybe + created_at?: InputMaybe + exercises?: InputMaybe + id?: InputMaybe + name?: InputMaybe + updated_at?: InputMaybe + url?: InputMaybe + user_course_service_progresses?: InputMaybe +} + export type ServiceWhereUniqueInput = { id?: InputMaybe } @@ -1635,6 +2009,11 @@ export type StoredData = { user_id: Scalars["String"] } +export type StoredDataOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type StringNullableFilter = { contains?: InputMaybe endsWith?: InputMaybe @@ -1666,7 +2045,7 @@ export type StudyModule = { export type StudyModulecoursesArgs = { language?: InputMaybe - orderBy?: InputMaybe + orderBy?: InputMaybe } export type StudyModulestudy_module_translationsArgs = { @@ -1681,17 +2060,32 @@ export type StudyModuleCreateArg = { order?: InputMaybe slug: Scalars["String"] study_module_translations?: InputMaybe< - Array> + Array > } export type StudyModuleOrderByInput = { + id?: InputMaybe + image?: InputMaybe + name?: InputMaybe + order?: InputMaybe + slug?: InputMaybe +} + +export type StudyModuleOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + +export type StudyModuleOrderByWithRelationInput = { + courses?: InputMaybe created_at?: InputMaybe id?: InputMaybe image?: InputMaybe name?: InputMaybe order?: InputMaybe slug?: InputMaybe + study_module_translations?: InputMaybe updated_at?: InputMaybe } @@ -1714,6 +2108,11 @@ export type StudyModuleTranslationCreateInput = { study_module?: InputMaybe } +export type StudyModuleTranslationOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type StudyModuleTranslationUpsertInput = { description: Scalars["String"] id?: InputMaybe @@ -1734,7 +2133,7 @@ export type StudyModuleUpsertArg = { order?: InputMaybe slug: Scalars["String"] study_module_translations?: InputMaybe< - Array> + Array > } @@ -1743,6 +2142,108 @@ export type StudyModuleWhereUniqueInput = { slug?: InputMaybe } +export type Tag = { + __typename?: "Tag" + course_tags: Array + created_at: Maybe + description: Maybe + hidden: Maybe + id: Scalars["String"] + language: Maybe + name: Maybe + tag_translations: Array + tag_types: Array + types: Maybe> + updated_at: Maybe +} + +export type Tagcourse_tagsArgs = { + cursor?: InputMaybe + skip?: InputMaybe + take?: InputMaybe +} + +export type Tagtag_translationsArgs = { + cursor?: InputMaybe + skip?: InputMaybe + take?: InputMaybe +} + +export type Tagtag_typesArgs = { + cursor?: InputMaybe + skip?: InputMaybe + take?: InputMaybe +} + +export type TagCreateInput = { + hidden?: InputMaybe + id?: InputMaybe + tag_translations?: InputMaybe> + types?: InputMaybe> +} + +export type TagTranslation = { + __typename?: "TagTranslation" + created_at: Maybe + description: Maybe + language: Scalars["String"] + name: Scalars["String"] + tag: Tag + tag_id: Scalars["String"] + updated_at: Maybe +} + +export type TagTranslationCreateOrUpdateInput = { + description?: InputMaybe + language: Scalars["String"] + name: Scalars["String"] + tag_id?: InputMaybe +} + +export type TagTranslationNameLanguageCompoundUniqueInput = { + language: Scalars["String"] + name: Scalars["String"] +} + +export type TagTranslationTag_idLanguageCompoundUniqueInput = { + language: Scalars["String"] + tag_id: Scalars["String"] +} + +export type TagTranslationWhereUniqueInput = { + name_language?: InputMaybe + tag_id_language?: InputMaybe +} + +export type TagType = { + __typename?: "TagType" + created_at: Maybe + name: Scalars["String"] + tags: Array + updated_at: Maybe +} + +export type TagTypetagsArgs = { + cursor?: InputMaybe + skip?: InputMaybe + take?: InputMaybe +} + +export type TagTypeWhereUniqueInput = { + name?: InputMaybe +} + +export type TagUpsertInput = { + hidden?: InputMaybe + id: Scalars["ID"] + tag_translations?: InputMaybe> + types?: InputMaybe> +} + +export type TagWhereUniqueInput = { + id?: InputMaybe +} + export type User = { __typename?: "User" ab_enrollments: Array @@ -1902,6 +2403,11 @@ export type UserCourseProgressuser_course_service_progressesArgs = { take?: InputMaybe } +export type UserCourseProgressOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type UserCourseProgressWhereUniqueInput = { id?: InputMaybe } @@ -1912,7 +2418,7 @@ export type UserCourseServiceProgress = { course_id: Maybe created_at: Maybe id: Scalars["String"] - progress: Maybe>> + progress: Array service: Maybe service_id: Maybe timestamp: Maybe @@ -1923,6 +2429,11 @@ export type UserCourseServiceProgress = { user_id: Maybe } +export type UserCourseServiceProgressOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type UserCourseServiceProgressWhereUniqueInput = { id?: InputMaybe } @@ -1952,6 +2463,11 @@ export type UserCourseSettingEdge = { node: UserCourseSetting } +export type UserCourseSettingOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type UserCourseSettingWhereUniqueInput = { id?: InputMaybe } @@ -1971,6 +2487,11 @@ export type UserCourseSettingsVisibilityCreateInput = { language: Scalars["String"] } +export type UserCourseSettingsVisibilityOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type UserCourseSettingsVisibilityUpsertInput = { course?: InputMaybe id?: InputMaybe @@ -2010,6 +2531,35 @@ export type UserEdge = { node: User } +export type UserOrderByWithRelationInput = { + ab_enrollments?: InputMaybe + administrator?: InputMaybe + completions?: InputMaybe + completions_registered?: InputMaybe + course_ownerships?: InputMaybe + course_stats_subscriptions?: InputMaybe + created_at?: InputMaybe + email?: InputMaybe + email_deliveries?: InputMaybe + exercise_completions?: InputMaybe + first_name?: InputMaybe + id?: InputMaybe + last_name?: InputMaybe + organizations?: InputMaybe + real_student_number?: InputMaybe + research_consent?: InputMaybe + stored_data?: InputMaybe + student_number?: InputMaybe + updated_at?: InputMaybe + upstream_id?: InputMaybe + user_course_progresses?: InputMaybe + user_course_service_progresses?: InputMaybe + user_course_settings?: InputMaybe + user_organizations?: InputMaybe + username?: InputMaybe + verified_users?: InputMaybe +} + export type UserOrganization = { __typename?: "UserOrganization" created_at: Maybe @@ -2022,6 +2572,11 @@ export type UserOrganization = { user_id: Maybe } +export type UserOrganizationOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type UserOrganizationWhereUniqueInput = { id?: InputMaybe } @@ -2052,6 +2607,11 @@ export type VerifiedUserArg = { personal_unique_code: Scalars["String"] } +export type VerifiedUserOrderByRelationAggregateInput = { + _count?: InputMaybe + count?: InputMaybe +} + export type VerifiedUserWhereUniqueInput = { id?: InputMaybe } @@ -2383,6 +2943,24 @@ export type CourseTranslationDetailedFieldsFragment = { name: string } +export type CourseTagFieldsFragment = { + __typename?: "CourseTag" + tag: { + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + } | null +} + export type CourseFieldsFragment = { __typename?: "Course" description: string | null @@ -2420,6 +2998,20 @@ export type CourseFieldsFragment = { slug: string name: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> photo: { __typename?: "Image" id: string @@ -2486,6 +3078,20 @@ export type EditorCourseFieldsFragment = { id: string language: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> course_translations: Array<{ __typename?: "CourseTranslation" id: string @@ -2588,6 +3194,20 @@ export type EditorCourseDetailedFieldsFragment = { id: string language: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> study_modules: Array<{ __typename?: "StudyModule" id: string @@ -2773,7 +3393,7 @@ export type ProgressCoreFieldsFragment = { course_id: string | null service_id: string | null user_id: string | null - progress: Array | null + progress: Array created_at: any | null updated_at: any | null service: { __typename?: "Service"; name: string; id: string } | null @@ -2877,6 +3497,20 @@ export type StudyModuleFieldsWithCoursesFragment = { slug: string name: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> photo: { __typename?: "Image" id: string @@ -2893,6 +3527,29 @@ export type StudyModuleFieldsWithCoursesFragment = { }> | null } +export type TagCoreFieldsFragment = { + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> +} + +export type TagTranslationFieldsFragment = { + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string +} + export type UserCoreFieldsFragment = { __typename?: "User" id: string @@ -2974,7 +3631,7 @@ export type UserProgressesFieldsFragment = { course_id: string | null service_id: string | null user_id: string | null - progress: Array | null + progress: Array created_at: any | null updated_at: any | null service: { __typename?: "Service"; name: string; id: string } | null @@ -3109,7 +3766,7 @@ export type UserCourseServiceProgressCoreFieldsFragment = { course_id: string | null service_id: string | null user_id: string | null - progress: Array | null + progress: Array created_at: any | null updated_at: any | null service: { __typename?: "Service"; name: string; id: string } | null @@ -3195,7 +3852,7 @@ export type StudentProgressesQueryNodeFieldsFragment = { course_id: string | null service_id: string | null user_id: string | null - progress: Array | null + progress: Array created_at: any | null updated_at: any | null service: { __typename?: "Service"; name: string; id: string } | null @@ -3347,7 +4004,7 @@ export type UserCourseSummaryCoreFieldsFragment = { course_id: string | null service_id: string | null user_id: string | null - progress: Array | null + progress: Array created_at: any | null updated_at: any | null service: { __typename?: "Service"; name: string; id: string } | null @@ -3561,6 +4218,20 @@ export type AddCourseMutation = { id: string language: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> study_modules: Array<{ __typename?: "StudyModule" id: string @@ -3688,6 +4359,20 @@ export type UpdateCourseMutation = { id: string language: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> study_modules: Array<{ __typename?: "StudyModule" id: string @@ -4156,6 +4841,20 @@ export type CoursesQuery = { slug: string name: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> photo: { __typename?: "Image" id: string @@ -4232,6 +4931,20 @@ export type EditorCoursesQuery = { id: string language: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> course_translations: Array<{ __typename?: "CourseTranslation" id: string @@ -4416,6 +5129,20 @@ export type CourseEditorDetailsQuery = { id: string language: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> study_modules: Array<{ __typename?: "StudyModule" id: string @@ -4680,6 +5407,20 @@ export type StudyModulesWithCoursesQuery = { slug: string name: string }> + tags: Array<{ + __typename?: "Tag" + id: string + hidden: boolean | null + types: Array | null + name: string | null + tag_translations: Array<{ + __typename?: "TagTranslation" + tag_id: string + name: string + description: string | null + language: string + }> + }> photo: { __typename?: "Image" id: string @@ -4933,7 +5674,7 @@ export type UserSummaryQuery = { course_id: string | null service_id: string | null user_id: string | null - progress: Array | null + progress: Array created_at: any | null updated_at: any | null service: { __typename?: "Service"; name: string; id: string } | null @@ -5200,7 +5941,7 @@ export type CurrentUserProgressesQuery = { course_id: string | null service_id: string | null user_id: string | null - progress: Array | null + progress: Array created_at: any | null updated_at: any | null service: { __typename?: "Service"; name: string; id: string } | null @@ -5432,7 +6173,7 @@ export type StudentProgressesQuery = { course_id: string | null service_id: string | null user_id: string | null - progress: Array | null + progress: Array created_at: any | null updated_at: any | null service: { @@ -6018,6 +6759,94 @@ export const CompletionsQueryConnectionFieldsFragmentDoc = { }, ], } as unknown as DocumentNode +export const TagTranslationFieldsFragmentDoc = { + kind: "Document", + definitions: [ + { + kind: "FragmentDefinition", + name: { kind: "Name", value: "TagTranslationFields" }, + typeCondition: { + kind: "NamedType", + name: { kind: "Name", value: "TagTranslation" }, + }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "tag_id" } }, + { kind: "Field", name: { kind: "Name", value: "name" } }, + { kind: "Field", name: { kind: "Name", value: "description" } }, + { kind: "Field", name: { kind: "Name", value: "language" } }, + ], + }, + }, + ], +} as unknown as DocumentNode +export const TagCoreFieldsFragmentDoc = { + kind: "Document", + definitions: [ + { + kind: "FragmentDefinition", + name: { kind: "Name", value: "TagCoreFields" }, + typeCondition: { + kind: "NamedType", + name: { kind: "Name", value: "Tag" }, + }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { kind: "Field", name: { kind: "Name", value: "id" } }, + { kind: "Field", name: { kind: "Name", value: "hidden" } }, + { kind: "Field", name: { kind: "Name", value: "types" } }, + { kind: "Field", name: { kind: "Name", value: "name" } }, + { + kind: "Field", + name: { kind: "Name", value: "tag_translations" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "FragmentSpread", + name: { kind: "Name", value: "TagTranslationFields" }, + }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode +export const CourseTagFieldsFragmentDoc = { + kind: "Document", + definitions: [ + { + kind: "FragmentDefinition", + name: { kind: "Name", value: "CourseTagFields" }, + typeCondition: { + kind: "NamedType", + name: { kind: "Name", value: "CourseTag" }, + }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "Field", + name: { kind: "Name", value: "tag" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "FragmentSpread", + name: { kind: "Name", value: "TagCoreFields" }, + }, + ], + }, + }, + ], + }, + }, + ], +} as unknown as DocumentNode export const CourseTranslationCoreFieldsFragmentDoc = { kind: "Document", definitions: [ @@ -6135,6 +6964,19 @@ export const CourseFieldsFragmentDoc = { ], }, }, + { + kind: "Field", + name: { kind: "Name", value: "tags" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "FragmentSpread", + name: { kind: "Name", value: "TagCoreFields" }, + }, + ], + }, + }, ], }, }, @@ -6209,6 +7051,19 @@ export const EditorCourseFieldsFragmentDoc = { ], }, }, + { + kind: "Field", + name: { kind: "Name", value: "tags" }, + selectionSet: { + kind: "SelectionSet", + selections: [ + { + kind: "FragmentSpread", + name: { kind: "Name", value: "TagCoreFields" }, + }, + ], + }, + }, ], }, }, @@ -7576,6 +8431,8 @@ export const AddCourseDocument = { ...ImageCoreFieldsFragmentDoc.definitions, ...CourseTranslationCoreFieldsFragmentDoc.definitions, ...StudyModuleCoreFieldsFragmentDoc.definitions, + ...TagCoreFieldsFragmentDoc.definitions, + ...TagTranslationFieldsFragmentDoc.definitions, ...CourseTranslationDetailedFieldsFragmentDoc.definitions, ...OpenUniversityRegistrationLinkCoreFieldsFragmentDoc.definitions, ], @@ -7672,6 +8529,8 @@ export const UpdateCourseDocument = { ...ImageCoreFieldsFragmentDoc.definitions, ...CourseTranslationCoreFieldsFragmentDoc.definitions, ...StudyModuleCoreFieldsFragmentDoc.definitions, + ...TagCoreFieldsFragmentDoc.definitions, + ...TagTranslationFieldsFragmentDoc.definitions, ...CourseTranslationDetailedFieldsFragmentDoc.definitions, ...OpenUniversityRegistrationLinkCoreFieldsFragmentDoc.definitions, ...EmailTemplateCoreFieldsFragmentDoc.definitions, @@ -9062,6 +9921,8 @@ export const CoursesDocument = { ...ImageCoreFieldsFragmentDoc.definitions, ...CourseTranslationCoreFieldsFragmentDoc.definitions, ...StudyModuleCoreFieldsFragmentDoc.definitions, + ...TagCoreFieldsFragmentDoc.definitions, + ...TagTranslationFieldsFragmentDoc.definitions, ], } as unknown as DocumentNode export const EditorCoursesDocument = { @@ -9202,6 +10063,8 @@ export const EditorCoursesDocument = { ...ImageCoreFieldsFragmentDoc.definitions, ...CourseTranslationCoreFieldsFragmentDoc.definitions, ...StudyModuleCoreFieldsFragmentDoc.definitions, + ...TagCoreFieldsFragmentDoc.definitions, + ...TagTranslationFieldsFragmentDoc.definitions, ], } as unknown as DocumentNode export const CourseFromSlugDocument = { @@ -9380,6 +10243,8 @@ export const CourseEditorDetailsDocument = { ...ImageCoreFieldsFragmentDoc.definitions, ...CourseTranslationCoreFieldsFragmentDoc.definitions, ...StudyModuleCoreFieldsFragmentDoc.definitions, + ...TagCoreFieldsFragmentDoc.definitions, + ...TagTranslationFieldsFragmentDoc.definitions, ...CourseTranslationDetailedFieldsFragmentDoc.definitions, ...OpenUniversityRegistrationLinkCoreFieldsFragmentDoc.definitions, ], @@ -9879,6 +10744,8 @@ export const StudyModulesWithCoursesDocument = { ...CourseCoreFieldsFragmentDoc.definitions, ...ImageCoreFieldsFragmentDoc.definitions, ...CourseTranslationCoreFieldsFragmentDoc.definitions, + ...TagCoreFieldsFragmentDoc.definitions, + ...TagTranslationFieldsFragmentDoc.definitions, ], } as unknown as DocumentNode< StudyModulesWithCoursesQuery, diff --git a/frontend/hooks/useEditorCourses.tsx b/frontend/hooks/useEditorCourses.tsx index d92fd3b7e..74833cc5b 100644 --- a/frontend/hooks/useEditorCourses.tsx +++ b/frontend/hooks/useEditorCourses.tsx @@ -31,8 +31,8 @@ export function useEditorCourses({ slug }: UseEditorCoursesProps) { } = useQuery(CourseEditorOtherCoursesDocument) return { - loading: courseLoading || studyModulesLoading || coursesLoading, - error: courseError || studyModulesError || coursesError, + loading: courseLoading ?? studyModulesLoading ?? coursesLoading, + error: courseError ?? studyModulesError ?? coursesError, courseData, studyModulesData, coursesData, diff --git a/frontend/lib/with-apollo-client/index.tsx b/frontend/lib/with-apollo-client/index.tsx index 32ff61484..1109adc0c 100644 --- a/frontend/lib/with-apollo-client/index.tsx +++ b/frontend/lib/with-apollo-client/index.tsx @@ -2,7 +2,7 @@ import { NextPageContext } from "next" import { AppContext } from "next/app" import { renderToString } from "react-dom/server" -import { type ApolloClient, ApolloProvider } from "@apollo/client" +import { ApolloProvider, type ApolloClient } from "@apollo/client" import fetchUserDetails from "./fetch-user-details" import getApollo, { initNewApollo } from "./get-apollo" diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f3a27d537..ff97894da 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -96,7 +96,7 @@ "cors": "^2.8.5", "express-graphql": "^0.12.0", "source-map-support": "^0.5.21", - "typescript": "^4.7.4" + "typescript": "^4.9.4" } }, "../../tmc-client-js": { @@ -6280,7 +6280,7 @@ "yarn": "^1.22.17" }, "engines": { - "node": ">=12.0.0" + "node": ">=8.0.0" } }, "node_modules/@oclif/plugin-plugins/node_modules/ansi-styles": { @@ -6446,10 +6446,10 @@ "@oclif/core": "^1.0.8", "chalk": "^4.1.0", "debug": "^4.1.0", - "fs-extra": "^9.0.1", + "fs-extra": "^7.0.0", "http-call": "^5.2.2", - "lodash": "^4.17.21", - "semver": "^7.3.2" + "lodash.template": "^4.4.0", + "semver": "^5.6.0" }, "engines": { "node": ">=12.0.0" @@ -6505,26 +6505,19 @@ "dev": true }, "node_modules/@oclif/plugin-warn-if-update-available/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, "engines": { - "node": ">=10" + "node": ">=6 <7 || >=8" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, "node_modules/@oclif/plugin-warn-if-update-available/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -6534,33 +6527,6 @@ "node": ">=8" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@oclif/plugin-warn-if-update-available/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6573,15 +6539,6 @@ "node": ">=8" } }, - "node_modules/@oclif/plugin-warn-if-update-available/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@oclif/screen": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-3.0.2.tgz", @@ -8278,7 +8235,7 @@ "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/apollo/node_modules/has-flag": { @@ -11756,8 +11713,7 @@ "integrity": "sha512-zyRGZQkjp5lgYYRUJS7hbEAhEtfslzwN5ScSnLXhaF2OEtiVC8LW+5mbaIqlFpIE95iFhukrKaLm0Rdt/w2lNg==", "dev": true, "dependencies": { - "execa": "^5.0.0", - "fromentries": "^1.3.2", + "execa": "^4.0.0", "java-properties": "^1.0.0" }, "engines": { @@ -11779,19 +11735,19 @@ } }, "node_modules/env-ci/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" }, "engines": { @@ -11802,26 +11758,20 @@ } }, "node_modules/env-ci/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/env-ci/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, "node_modules/env-ci/node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -13319,26 +13269,6 @@ "readable-stream": "^2.0.0" } }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -16697,6 +16627,12 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", + "dev": true + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -16774,6 +16710,25 @@ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -23137,9 +23092,9 @@ "peer": true }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -29683,10 +29638,10 @@ "@oclif/core": "^1.0.8", "chalk": "^4.1.0", "debug": "^4.1.0", - "fs-extra": "^9.0.1", + "fs-extra": "^7.0.0", "http-call": "^5.2.2", - "lodash": "^4.17.21", - "semver": "^7.3.2" + "lodash.template": "^4.4.0", + "semver": "^5.6.0" }, "dependencies": { "ansi-styles": { @@ -29724,48 +29679,22 @@ "dev": true }, "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -29774,12 +29703,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true } } }, @@ -33933,8 +33856,7 @@ "integrity": "sha512-zyRGZQkjp5lgYYRUJS7hbEAhEtfslzwN5ScSnLXhaF2OEtiVC8LW+5mbaIqlFpIE95iFhukrKaLm0Rdt/w2lNg==", "dev": true, "requires": { - "execa": "^5.0.0", - "fromentries": "^1.3.2", + "execa": "^4.0.0", "java-properties": "^1.0.0" }, "dependencies": { @@ -33950,33 +33872,30 @@ } }, "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dev": true, "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" } }, "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } }, "is-stream": { "version": "2.0.1", @@ -35129,12 +35048,6 @@ "readable-stream": "^2.0.0" } }, - "fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true - }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -37691,6 +37604,12 @@ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", + "dev": true + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", @@ -37768,6 +37687,25 @@ "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", @@ -42625,9 +42563,9 @@ "peer": true }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true }, "ua-parser-js": { diff --git a/frontend/package.json b/frontend/package.json index 788e701a7..60a1845c7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -106,7 +106,7 @@ "cors": "^2.8.5", "express-graphql": "^0.12.0", "source-map-support": "^0.5.21", - "typescript": "^4.7.4" + "typescript": "^4.9.4" }, "overrides": { "graphql": "16.5.0" diff --git a/frontend/pages/courses.tsx b/frontend/pages/courses.tsx index 0c146b0ef..02ef17f62 100644 --- a/frontend/pages/courses.tsx +++ b/frontend/pages/courses.tsx @@ -133,7 +133,7 @@ function useCourseSearch() { return { loading: editorLoading || handlersLoading, - error: editorError || handlersError, + error: editorError ?? handlersError, handlersData, editorData, status, diff --git a/frontend/pages/register.tsx b/frontend/pages/register.tsx index 47c34a705..495c10675 100644 --- a/frontend/pages/register.tsx +++ b/frontend/pages/register.tsx @@ -129,13 +129,10 @@ function useRegisterOrganization(searchFilter: string) { error: organizationsError, loading: organizationsLoading, } = useQuery(OrganizationsDocument) - const { - data: userOrganizationsData, - error: userOrganizationsError, - // loading: userOrganizationsLoading, - } = useQuery(UserOrganizationsDocument, { - variables: { user_id: currentUser?.id }, - }) + const { data: userOrganizationsData, error: userOrganizationsError } = + useQuery(UserOrganizationsDocument, { + variables: { user_id: currentUser!.id }, + }) const [addUserOrganization] = useMutation(AddUserOrganizationDocument, { refetchQueries: [ { @@ -145,7 +142,6 @@ function useRegisterOrganization(searchFilter: string) { ], }) - // const [updateUserOrganization] = useMutation(UpdateUserOrganizationMutation) const [deleteUserOrganization] = useMutation(DeleteUserOrganizationDocument, { refetchQueries: [ { @@ -249,7 +245,7 @@ function useRegisterOrganization(searchFilter: string) { } return { - error: organizationsError || userOrganizationsError, + error: organizationsError ?? userOrganizationsError, loading: organizationsLoading, organizations, filteredOrganizations, @@ -258,23 +254,55 @@ function useRegisterOrganization(searchFilter: string) { } } -const Register = () => { +const OrganizationItems = () => { const t = useTranslator(RegistrationTranslations) - const { searchFilter, cancelFilterDebounce, searchBox, setSearchBox } = - useSearchBox() + + const { searchFilter } = useSearchBox() const { error, - loading, - toggleMembership, organizations, + loading, filteredOrganizations, memberships, + toggleMembership, } = useRegisterOrganization(searchFilter) - if (error /*organizationsError || userOrganizationsError*/) { + if (error) { return } + if (loading) { + return ( + <> + {range(5).map((i) => ( + + ))} + + ) + } + + if (!organizations || Object.keys(organizations).length === 0) { + return
{t("noResults", { search: searchFilter })}
+ } + + return ( + <> + {Object.entries(filteredOrganizations).map(([id, organization]) => ( + + ))} + + ) +} + +const Register = () => { + const t = useTranslator(RegistrationTranslations) + const { cancelFilterDebounce, searchBox, setSearchBox } = useSearchBox() + return (
@@ -307,22 +335,7 @@ const Register = () => { ), }} /> - <> - {loading || !Object.keys(organizations).length ? ( - range(5).map((i) => ) - ) : Object.keys(filteredOrganizations).length ? ( - Object.entries(filteredOrganizations).map(([id, organization]) => ( - - )) - ) : ( -
{t("noResults", { search: searchFilter })}
- )} - + ) diff --git a/frontend/server.js b/frontend/server.js index 814f4debe..a70d94def 100644 --- a/frontend/server.js +++ b/frontend/server.js @@ -11,6 +11,7 @@ const next = require("next") const compression = require("compression") const Redirects = require("./Redirects") +// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const port = process.env.PORT || 3000 const app = next({ dev: !isProduction }) const handle = app.getRequestHandler() diff --git a/frontend/translations/_new/courses/index.ts b/frontend/translations/_new/courses/index.ts index 49555b78f..7e8fe3e6d 100644 --- a/frontend/translations/_new/courses/index.ts +++ b/frontend/translations/_new/courses/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/breadcrumbs/index.ts b/frontend/translations/breadcrumbs/index.ts index 25da0d3b5..96e48ead3 100644 --- a/frontend/translations/breadcrumbs/index.ts +++ b/frontend/translations/breadcrumbs/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/common/index.ts b/frontend/translations/common/index.ts index 6b3ec10dc..d5ea4eb4c 100644 --- a/frontend/translations/common/index.ts +++ b/frontend/translations/common/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import se from "./se.json" diff --git a/frontend/translations/completions/index.ts b/frontend/translations/completions/index.ts index f46a00e6d..beb0f76ea 100644 --- a/frontend/translations/completions/index.ts +++ b/frontend/translations/completions/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/courses/index.ts b/frontend/translations/courses/index.ts index 49555b78f..7e8fe3e6d 100644 --- a/frontend/translations/courses/index.ts +++ b/frontend/translations/courses/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/faq/index.ts b/frontend/translations/faq/index.ts index d17643e70..ec0cff61b 100644 --- a/frontend/translations/faq/index.ts +++ b/frontend/translations/faq/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/home/index.ts b/frontend/translations/home/index.ts index b83cc0455..549229d6a 100644 --- a/frontend/translations/home/index.ts +++ b/frontend/translations/home/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/installation/index.ts b/frontend/translations/installation/index.ts index a38d4b7ea..1b9ae3158 100644 --- a/frontend/translations/installation/index.ts +++ b/frontend/translations/installation/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/navi/index.ts b/frontend/translations/navi/index.ts index 10bd8a3c6..9ed6907ce 100644 --- a/frontend/translations/navi/index.ts +++ b/frontend/translations/navi/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/pages/index.ts b/frontend/translations/pages/index.ts index 0e6c21ffe..8405beb3b 100644 --- a/frontend/translations/pages/index.ts +++ b/frontend/translations/pages/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/profile/index.ts b/frontend/translations/profile/index.ts index 46ac1606c..bb7578d8a 100644 --- a/frontend/translations/profile/index.ts +++ b/frontend/translations/profile/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/register-completion/index.ts b/frontend/translations/register-completion/index.ts index a9e969fac..320ef1206 100644 --- a/frontend/translations/register-completion/index.ts +++ b/frontend/translations/register-completion/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import se from "./se.json" diff --git a/frontend/translations/register/index.ts b/frontend/translations/register/index.ts index 430c5233a..4ba2a6e20 100644 --- a/frontend/translations/register/index.ts +++ b/frontend/translations/register/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/sign-up/index.ts b/frontend/translations/sign-up/index.ts index b16612346..05bc751bd 100644 --- a/frontend/translations/sign-up/index.ts +++ b/frontend/translations/sign-up/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/study-modules/index.ts b/frontend/translations/study-modules/index.ts index 46df0b15a..b72b24c9e 100644 --- a/frontend/translations/study-modules/index.ts +++ b/frontend/translations/study-modules/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/teachers/index.ts b/frontend/translations/teachers/index.ts index 822e20665..1f8a26eb0 100644 --- a/frontend/translations/teachers/index.ts +++ b/frontend/translations/teachers/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/translations/users/index.ts b/frontend/translations/users/index.ts index 8e7816824..c0fa6325f 100644 --- a/frontend/translations/users/index.ts +++ b/frontend/translations/users/index.ts @@ -1,5 +1,4 @@ // generated Wed Nov 23 2022 13:42:15 GMT+0200 (Itä-Euroopan normaaliaika) - import en from "./en.json" import fi from "./fi.json" import { TranslationDictionary } from "/translations" diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 6964d7337..3bdc5e3fb 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -39,6 +39,7 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, + "strictNullChecks": true, "target": "esnext", "forceConsistentCasingInFileNames": true, "esModuleInterop": true, diff --git a/package-lock.json b/package-lock.json index 4162e5d59..f89ec13bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,22 +9,23 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@next/eslint-plugin-next": "12.2.2", - "@types/mime-types": "^2.1.1", - "@types/node": "^18.0.0", - "os-name": "^5.0.1" + "@ianvs/prettier-plugin-sort-imports": "^3.7.1", + "os-name": "^5.1.0" }, "devDependencies": { - "@ianvs/prettier-plugin-sort-imports": "^3.4.2", - "@typescript-eslint/eslint-plugin": "^5.19.0", - "@typescript-eslint/parser": "^5.19.0", - "eslint": "^8.13.0", + "@next/eslint-plugin-next": "12.2.2", + "@types/mime-types": "^2.1.1", + "@types/node": "^18.11.18", + "@typescript-eslint/eslint-plugin": "^5.48.1", + "@typescript-eslint/parser": "^5.48.1", + "eslint": "^8.31.0", + "eslint-config-prettier": "^8.6.0", "eslint-plugin-eslint-custom-rules": "file:eslint-custom-rules", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react-hooks": "^4.4.0", - "husky": "^8.0.1", - "prettier": "^2.6.2", - "typescript": "^4.6.3" + "eslint-plugin-jsx-a11y": "^6.7.0", + "eslint-plugin-react-hooks": "^4.6.0", + "husky": "^8.0.3", + "prettier": "^2.8.2", + "typescript": "^4.9.4" } }, "eslint-custom-rules": { @@ -40,7 +41,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -53,7 +53,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, "dependencies": { "@babel/highlight": "^7.16.7" }, @@ -65,7 +64,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -74,7 +72,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -104,7 +101,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -113,7 +109,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", - "dev": true, "dependencies": { "@babel/types": "^7.18.2", "@jridgewell/gen-mapping": "^0.3.0", @@ -127,7 +122,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -141,7 +135,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.17.10", "@babel/helper-validator-option": "^7.16.7", @@ -159,7 +152,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -168,7 +160,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -177,7 +168,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, "dependencies": { "@babel/template": "^7.16.7", "@babel/types": "^7.17.0" @@ -190,7 +180,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -202,7 +191,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -214,7 +202,6 @@ "version": "7.18.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -233,7 +220,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", - "dev": true, "dependencies": { "@babel/types": "^7.18.2" }, @@ -245,7 +231,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -257,7 +242,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -266,7 +250,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -275,7 +258,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", - "dev": true, "dependencies": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.18.2", @@ -289,7 +271,6 @@ "version": "7.17.12", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", @@ -303,7 +284,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "dependencies": { "color-convert": "^1.9.0" }, @@ -315,7 +295,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -329,7 +308,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "dependencies": { "color-name": "1.1.3" } @@ -337,14 +315,12 @@ "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/@babel/highlight/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, "engines": { "node": ">=0.8.0" } @@ -353,7 +329,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, "engines": { "node": ">=4" } @@ -362,7 +337,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -374,7 +348,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -383,25 +356,12 @@ } }, "node_modules/@babel/runtime": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.5.tgz", - "integrity": "sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", + "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", "dev": true, "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.15.3.tgz", - "integrity": "sha512-30A3lP+sRL6ml8uhoJSs+8jwpKzbw8CqBvDc1laeptxPm5FahumJxirigcbD2qTs71Sonvj1cyZB0OKGAmxQ+A==", - "dev": true, - "dependencies": { - "core-js-pure": "^3.16.0", - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" @@ -411,7 +371,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", @@ -425,7 +384,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.18.2", @@ -446,7 +404,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -455,7 +412,6 @@ "version": "7.18.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" @@ -465,15 +421,15 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.4.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -482,22 +438,38 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", - "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -505,10 +477,9 @@ "dev": true }, "node_modules/@ianvs/prettier-plugin-sort-imports": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-3.4.2.tgz", - "integrity": "sha512-HB2BLfnm3Jee+GiGtK7f5hLcFbF54VbSAoH9UEaWpjMmrbaZCTViJeuXsycA1Adm2colaHCpqhLW5E70umh6ug==", - "dev": true, + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-3.7.1.tgz", + "integrity": "sha512-XDnBUUruJY9KgNd7T2ZHnVPWo5B9NzVDCLEMm7HjXTA3rTtMg5Q46gYRjLvampDXSmN8+icu54aRE3IIT8U+1w==", "dependencies": { "@babel/core": "^7.17.7", "@babel/generator": "^7.17.7", @@ -516,17 +487,23 @@ "@babel/traverse": "^7.17.3", "@babel/types": "^7.17.0", "javascript-natural-sort": "0.7.1", - "lodash": "^4.17.21" + "lodash.clone": "^4.5.0", + "lodash.isequal": "^4.5.0" }, "peerDependencies": { + "@vue/compiler-sfc": ">=3.0.0", "prettier": "2.x" + }, + "peerDependenciesMeta": { + "@vue/compiler-sfc": { + "optional": true + } } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -539,7 +516,6 @@ "version": "3.0.8", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -548,7 +524,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -556,14 +531,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.14", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -573,6 +546,7 @@ "version": "12.2.2", "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.2.tgz", "integrity": "sha512-XOi0WzJhGH3Lk51SkSu9eZxF+IY1ZZhWcJTIGBycAbWU877IQa6+6KxMATWCOs7c+bmp6Sd8KywXJaDRxzu0JA==", + "dev": true, "dependencies": { "glob": "7.1.7" } @@ -581,6 +555,7 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -640,25 +615,33 @@ "node_modules/@types/mime-types": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", - "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==" + "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", + "dev": true }, "node_modules/@types/node": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", - "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==" + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz", - "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.1.tgz", + "integrity": "sha512-9nY5K1Rp2ppmpb9s9S2aBiF3xo5uExCehMDmYmmFqqyxgenbHJ3qbarcLt4ITgaD6r/2ypdlcFRdcuVPnks+fQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/type-utils": "5.29.0", - "@typescript-eslint/utils": "5.29.0", + "@typescript-eslint/scope-manager": "5.48.1", + "@typescript-eslint/type-utils": "5.48.1", + "@typescript-eslint/utils": "5.48.1", "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" @@ -681,14 +664,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", - "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.1.tgz", + "integrity": "sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", + "@typescript-eslint/scope-manager": "5.48.1", + "@typescript-eslint/types": "5.48.1", + "@typescript-eslint/typescript-estree": "5.48.1", "debug": "^4.3.4" }, "engines": { @@ -708,13 +691,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", - "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz", + "integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/visitor-keys": "5.29.0" + "@typescript-eslint/types": "5.48.1", + "@typescript-eslint/visitor-keys": "5.48.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -725,12 +708,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", - "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.1.tgz", + "integrity": "sha512-Hyr8HU8Alcuva1ppmqSYtM/Gp0q4JOp1F+/JH5D1IZm/bUBrV0edoewQZiEc1r6I8L4JL21broddxK8HAcZiqQ==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.29.0", + "@typescript-eslint/typescript-estree": "5.48.1", + "@typescript-eslint/utils": "5.48.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -751,9 +735,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", - "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", + "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -764,13 +748,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", - "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz", + "integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/visitor-keys": "5.29.0", + "@typescript-eslint/types": "5.48.1", + "@typescript-eslint/visitor-keys": "5.48.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -791,17 +775,19 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", - "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.1.tgz", + "integrity": "sha512-SmQuSrCGUOdmGMwivW14Z0Lj8dxG1mOFZ7soeJ0TQZEJcs3n5Ndgkg0A4bcMFzBELqLJ6GTHnEU+iIoaD6hFGA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.48.1", + "@typescript-eslint/types": "5.48.1", + "@typescript-eslint/typescript-estree": "5.48.1", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -815,12 +801,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", - "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", + "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/types": "5.48.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -832,9 +818,9 @@ } }, "node_modules/acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -899,28 +885,24 @@ "dev": true }, "node_modules/aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", "dev": true, "dependencies": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" - }, - "engines": { - "node": ">=6.0" + "deep-equal": "^2.0.5" } }, "node_modules/array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", "is-string": "^1.0.7" }, "engines": { @@ -939,36 +921,71 @@ "node": ">=8" } }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axe-core": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.3.5.tgz", - "integrity": "sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz", + "integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==", "dev": true, "engines": { "node": ">=4" } }, "node_modules/axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } }, "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -990,7 +1007,6 @@ "version": "4.21.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.0.tgz", "integrity": "sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -1040,7 +1056,6 @@ "version": "1.0.30001359", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001359.tgz", "integrity": "sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==", - "dev": true, "funding": [ { "type": "opencollective", @@ -1089,28 +1104,17 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "node_modules/convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, "dependencies": { "safe-buffer": "~5.1.1" } }, - "node_modules/core-js-pure": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.2.tgz", - "integrity": "sha512-oxKe64UH049mJqrKkynWp6Vu0Rlm/BTXO/bJZuN2mmR3RtOFNepLlSWDd1eo16PzHpQAoNG97rLU1V/YxesJjw==", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1125,16 +1129,15 @@ } }, "node_modules/damerau-levenshtein": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", - "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -1147,6 +1150,34 @@ } } }, + "node_modules/deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1154,15 +1185,19 @@ "dev": true }, "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "dev": true, "dependencies": { - "object-keys": "^1.0.12" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/dir-glob": { @@ -1192,35 +1227,46 @@ "node_modules/electron-to-chromium": { "version": "1.4.170", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.170.tgz", - "integrity": "sha512-rZ8PZLhK4ORPjFqLp9aqC4/S1j4qWFsPPz13xmWdrbBkU/LlxMcok+f+6f8YnQ57MiZwKtOaW15biZZsY5Igvw==", - "dev": true + "integrity": "sha512-rZ8PZLhK4ORPjFqLp9aqC4/S1j4qWFsPPz13xmWdrbBkU/LlxMcok+f+6f8YnQ57MiZwKtOaW15biZZsY5Igvw==" }, "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.0.tgz", + "integrity": "sha512-GUGtW7eXQay0c+PRq0sGIKSdaBorfVqsCMhGHo4elP7YVqZu9nCZS4UkK4gv71gOWNMra/PaSKD3ao1oWExO0g==", "dev": true, "dependencies": { "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.0", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.4", + "is-array-buffer": "^3.0.0", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", + "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" }, "engines": { "node": ">= 0.4" @@ -1229,6 +1275,48 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-get-iterator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -1250,7 +1338,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -1268,13 +1355,15 @@ } }, "node_modules/eslint": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz", - "integrity": "sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz", + "integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -1284,18 +1373,21 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -1306,8 +1398,7 @@ "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "bin": { "eslint": "bin/eslint.js" @@ -1319,28 +1410,44 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-config-prettier": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", + "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, "node_modules/eslint-plugin-eslint-custom-rules": { "resolved": "eslint-custom-rules", "link": true }, "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", - "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.0.tgz", + "integrity": "sha512-EGGRKhzejSzXKtjmEjWNtr4SK/DkMkSzkBH7g7e7moBDXZXrqaUIxkmD7uF93upMysc4dKYEJwupu7Dff+ShwA==", "dev": true, "dependencies": { - "@babel/runtime": "^7.16.3", - "aria-query": "^4.2.2", - "array-includes": "^3.1.4", + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", "ast-types-flow": "^0.0.7", - "axe-core": "^4.3.5", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "has": "^1.0.3", - "jsx-ast-utils": "^3.2.1", - "language-tags": "^1.0.5", - "minimatch": "^3.0.4" + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" }, "engines": { "node": ">=4.0" @@ -1355,6 +1462,15 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-plugin-react-hooks": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", @@ -1451,17 +1567,20 @@ } }, "node_modules/espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", "dev": true, "dependencies": { - "acorn": "^8.7.1", + "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { @@ -1553,9 +1672,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1581,9 +1700,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -1613,6 +1732,22 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -1632,10 +1767,20 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "node_modules/function-bind": { "version": "1.1.1", @@ -1643,30 +1788,50 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1732,9 +1897,9 @@ } }, "node_modules/globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -1746,6 +1911,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -1766,6 +1946,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1779,9 +1977,9 @@ } }, "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1796,10 +1994,22 @@ "node": ">=8" } }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "dev": true, "engines": { "node": ">= 0.4" @@ -1808,7 +2018,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-tostringtag": { + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", @@ -1832,9 +2054,9 @@ } }, "node_modules/husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true, "bin": { "husky": "lib/bin.js" @@ -1884,6 +2106,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -1892,15 +2115,16 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz", + "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.0", + "get-intrinsic": "^1.1.3", "has": "^1.0.3", "side-channel": "^1.0.4" }, @@ -1908,6 +2132,36 @@ "node": ">= 0.4" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", + "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -1937,9 +2191,9 @@ } }, "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "engines": { "node": ">= 0.4" @@ -1984,6 +2238,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -2006,9 +2269,9 @@ } }, "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "dependencies": { "has-tostringtag": "^1.0.0" @@ -2020,6 +2283,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -2036,11 +2308,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2086,6 +2370,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -2098,6 +2410,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2106,14 +2437,22 @@ "node_modules/javascript-natural-sort": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dev": true + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, + "node_modules/js-sdsl": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", + "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -2131,7 +2470,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" }, @@ -2155,7 +2493,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -2164,13 +2501,13 @@ } }, "node_modules/jsx-ast-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", - "integrity": "sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", "dev": true, "dependencies": { - "array-includes": "^3.1.3", - "object.assign": "^4.1.2" + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" }, "engines": { "node": ">=4.0" @@ -2204,11 +2541,30 @@ "node": ">= 0.8.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -2229,9 +2585,9 @@ } }, "node_modules/macos-release": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.0.1.tgz", - "integrity": "sha512-3l6OrhdDg2H2SigtuN3jBh+5dRJRWxNKuJTPBbGeNJTsmt/pj9PO25wYaNb05NuNmAsl435j4rDP6rgNXz7s7g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.1.0.tgz", + "integrity": "sha512-/M/R0gCDgM+Cv1IuBG1XGdfTFnMEG6PZeT+KGWHO/OG+imqmaD9CH5vHBTycEM3+Kc4uG2Il+tFAuUWLqQOeUA==", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -2278,6 +2634,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -2288,8 +2645,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -2297,11 +2653,16 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/node-releases": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", - "dev": true + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" }, "node_modules/npm-run-path": { "version": "4.0.1", @@ -2315,14 +2676,30 @@ } }, "node_modules/object-inspect": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", - "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -2333,14 +2710,14 @@ } }, "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -2350,10 +2727,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "dependencies": { "wrappy": "1" } @@ -2390,11 +2799,11 @@ } }, "node_modules/os-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.0.1.tgz", - "integrity": "sha512-0EQpaHUHq7olp2/YFUr+0vZi9tMpDTblHGz+Ch5RntKxiRXOAY0JOz1UlxhSjMSksHvkm13eD6elJj3M8Ht/kw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.1.0.tgz", + "integrity": "sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==", "dependencies": { - "macos-release": "^3.0.1", + "macos-release": "^3.1.0", "windows-release": "^5.0.1" }, "engines": { @@ -2404,6 +2813,36 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2416,10 +2855,20 @@ "node": ">=6" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2444,8 +2893,7 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -2469,10 +2917,9 @@ } }, "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true, + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz", + "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==", "bin": { "prettier": "bin-prettier.js" }, @@ -2484,9 +2931,9 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz", + "integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==", "dev": true, "engines": { "node": ">=6" @@ -2513,11 +2960,28 @@ ] }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "dev": true }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -2590,8 +3054,21 @@ "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/semver": { "version": "7.3.7", @@ -2656,26 +3133,28 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2735,7 +3214,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -2797,10 +3275,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -2811,14 +3303,14 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" }, "funding": { @@ -2829,7 +3321,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -2860,12 +3351,6 @@ "punycode": "^2.1.0" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2896,6 +3381,41 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/windows-release": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-5.0.1.tgz", @@ -2922,13 +3442,26 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { @@ -2936,7 +3469,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.1.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -2946,7 +3478,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", - "dev": true, "requires": { "@babel/highlight": "^7.16.7" } @@ -2954,14 +3485,12 @@ "@babel/compat-data": { "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.5.tgz", - "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==", - "dev": true + "integrity": "sha512-BxhE40PVCBxVEJsSBhB6UWyAuqJRxGsAw8BdHMJ3AKGydcwuWW4kOO3HmqBQAdcq/OP+/DlTVxLvsCzRTnZuGg==" }, "@babel/core": { "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.5.tgz", "integrity": "sha512-MGY8vg3DxMnctw0LdvSEojOsumc70g0t18gNyUdAZqB1Rpd1Bqo/svHGvt+UJ6JcGX+DIekGFDxxIWofBxLCnQ==", - "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -2983,8 +3512,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -2992,7 +3520,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", - "dev": true, "requires": { "@babel/types": "^7.18.2", "@jridgewell/gen-mapping": "^0.3.0", @@ -3003,7 +3530,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -3016,7 +3542,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", - "dev": true, "requires": { "@babel/compat-data": "^7.17.10", "@babel/helper-validator-option": "^7.16.7", @@ -3027,22 +3552,19 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, "@babel/helper-environment-visitor": { "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", - "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", - "dev": true + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==" }, "@babel/helper-function-name": { "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/types": "^7.17.0" @@ -3052,7 +3574,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -3061,7 +3582,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -3070,7 +3590,6 @@ "version": "7.18.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", - "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -3086,7 +3605,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", - "dev": true, "requires": { "@babel/types": "^7.18.2" } @@ -3095,7 +3613,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -3103,20 +3620,17 @@ "@babel/helper-validator-identifier": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", - "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", - "dev": true + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==" }, "@babel/helper-validator-option": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" }, "@babel/helpers": { "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.18.2", @@ -3127,7 +3641,6 @@ "version": "7.17.12", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", @@ -3138,7 +3651,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -3147,7 +3659,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -3158,7 +3669,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -3166,26 +3676,22 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -3195,33 +3701,21 @@ "@babel/parser": { "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.5.tgz", - "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==", - "dev": true + "integrity": "sha512-YZWVaglMiplo7v8f1oMQ5ZPQr0vn7HPeZXxXWsxXJRjGVrzUFn9OxFQl1sb5wzfootjA/yChhW84BV+383FSOw==" }, "@babel/runtime": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.5.tgz", - "integrity": "sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/runtime-corejs3": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.15.3.tgz", - "integrity": "sha512-30A3lP+sRL6ml8uhoJSs+8jwpKzbw8CqBvDc1laeptxPm5FahumJxirigcbD2qTs71Sonvj1cyZB0OKGAmxQ+A==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", + "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", "dev": true, "requires": { - "core-js-pure": "^3.16.0", - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" } }, "@babel/template": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", @@ -3232,7 +3726,6 @@ "version": "7.18.5", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.5.tgz", "integrity": "sha512-aKXj1KT66sBj0vVzk6rEeAO6Z9aiiQ68wfDgge3nHhA/my6xMM/7HGQUNumKZaoa2qUPQ5whJG9aAifsxUKfLA==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.18.2", @@ -3249,8 +3742,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" } } }, @@ -3258,22 +3750,21 @@ "version": "7.18.4", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" } }, "@eslint/eslintrc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", - "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.15.0", + "espree": "^9.4.0", + "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -3282,16 +3773,22 @@ } }, "@humanwhocodes/config-array": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.3.tgz", - "integrity": "sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==", + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5" } }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, "@humanwhocodes/object-schema": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", @@ -3299,10 +3796,9 @@ "dev": true }, "@ianvs/prettier-plugin-sort-imports": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-3.4.2.tgz", - "integrity": "sha512-HB2BLfnm3Jee+GiGtK7f5hLcFbF54VbSAoH9UEaWpjMmrbaZCTViJeuXsycA1Adm2colaHCpqhLW5E70umh6ug==", - "dev": true, + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-3.7.1.tgz", + "integrity": "sha512-XDnBUUruJY9KgNd7T2ZHnVPWo5B9NzVDCLEMm7HjXTA3rTtMg5Q46gYRjLvampDXSmN8+icu54aRE3IIT8U+1w==", "requires": { "@babel/core": "^7.17.7", "@babel/generator": "^7.17.7", @@ -3310,14 +3806,14 @@ "@babel/traverse": "^7.17.3", "@babel/types": "^7.17.0", "javascript-natural-sort": "0.7.1", - "lodash": "^4.17.21" + "lodash.clone": "^4.5.0", + "lodash.isequal": "^4.5.0" } }, "@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, "requires": { "@jridgewell/set-array": "^1.0.0", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -3326,26 +3822,22 @@ "@jridgewell/resolve-uri": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz", - "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==", - "dev": true + "integrity": "sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w==" }, "@jridgewell/set-array": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" }, "@jridgewell/sourcemap-codec": { "version": "1.4.14", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "@jridgewell/trace-mapping": { "version": "0.3.14", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz", "integrity": "sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==", - "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -3355,6 +3847,7 @@ "version": "12.2.2", "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.2.tgz", "integrity": "sha512-XOi0WzJhGH3Lk51SkSu9eZxF+IY1ZZhWcJTIGBycAbWU877IQa6+6KxMATWCOs7c+bmp6Sd8KywXJaDRxzu0JA==", + "dev": true, "requires": { "glob": "7.1.7" }, @@ -3363,6 +3856,7 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3409,77 +3903,86 @@ "@types/mime-types": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", - "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==" + "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", + "dev": true }, "@types/node": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", - "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==" + "version": "18.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", + "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", + "dev": true + }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz", - "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.1.tgz", + "integrity": "sha512-9nY5K1Rp2ppmpb9s9S2aBiF3xo5uExCehMDmYmmFqqyxgenbHJ3qbarcLt4ITgaD6r/2ypdlcFRdcuVPnks+fQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/type-utils": "5.29.0", - "@typescript-eslint/utils": "5.29.0", + "@typescript-eslint/scope-manager": "5.48.1", + "@typescript-eslint/type-utils": "5.48.1", + "@typescript-eslint/utils": "5.48.1", "debug": "^4.3.4", - "functional-red-black-tree": "^1.0.1", "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "@typescript-eslint/parser": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz", - "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.48.1.tgz", + "integrity": "sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", + "@typescript-eslint/scope-manager": "5.48.1", + "@typescript-eslint/types": "5.48.1", + "@typescript-eslint/typescript-estree": "5.48.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz", - "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz", + "integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/visitor-keys": "5.29.0" + "@typescript-eslint/types": "5.48.1", + "@typescript-eslint/visitor-keys": "5.48.1" } }, "@typescript-eslint/type-utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz", - "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.1.tgz", + "integrity": "sha512-Hyr8HU8Alcuva1ppmqSYtM/Gp0q4JOp1F+/JH5D1IZm/bUBrV0edoewQZiEc1r6I8L4JL21broddxK8HAcZiqQ==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.29.0", + "@typescript-eslint/typescript-estree": "5.48.1", + "@typescript-eslint/utils": "5.48.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz", - "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", + "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz", - "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz", + "integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/visitor-keys": "5.29.0", + "@typescript-eslint/types": "5.48.1", + "@typescript-eslint/visitor-keys": "5.48.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3488,33 +3991,35 @@ } }, "@typescript-eslint/utils": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz", - "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.1.tgz", + "integrity": "sha512-SmQuSrCGUOdmGMwivW14Z0Lj8dxG1mOFZ7soeJ0TQZEJcs3n5Ndgkg0A4bcMFzBELqLJ6GTHnEU+iIoaD6hFGA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.29.0", - "@typescript-eslint/types": "5.29.0", - "@typescript-eslint/typescript-estree": "5.29.0", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.48.1", + "@typescript-eslint/types": "5.48.1", + "@typescript-eslint/typescript-estree": "5.48.1", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "eslint-utils": "^3.0.0", + "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz", - "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==", + "version": "5.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", + "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.29.0", + "@typescript-eslint/types": "5.48.1", "eslint-visitor-keys": "^3.3.0" } }, "acorn": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true }, "acorn-jsx": { @@ -3558,25 +4063,24 @@ "dev": true }, "aria-query": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", - "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", "dev": true, "requires": { - "@babel/runtime": "^7.10.2", - "@babel/runtime-corejs3": "^7.10.2" + "deep-equal": "^2.0.5" } }, "array-includes": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", - "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1", - "get-intrinsic": "^1.1.1", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", "is-string": "^1.0.7" } }, @@ -3586,33 +4090,56 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, + "array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + } + }, "ast-types-flow": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", "dev": true }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, "axe-core": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.3.5.tgz", - "integrity": "sha512-WKTW1+xAzhMS5dJsxWkliixlO/PqC4VhmO9T4juNYcaTg9jzWiJsou6m5pxWYGfigWbwzJWeFY6z47a+4neRXA==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz", + "integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==", "dev": true }, "axobject-query": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", - "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", - "dev": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "requires": { + "deep-equal": "^2.0.5" + } }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3631,7 +4158,6 @@ "version": "4.21.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.0.tgz", "integrity": "sha512-UQxE0DIhRB5z/zDz9iA03BOfxaN2+GQdBYH/2WrSIWEUrnpzTPJbhqt+umq6r3acaPRTW1FNTkrcp0PXgtFkvA==", - "dev": true, "requires": { "caniuse-lite": "^1.0.30001358", "electron-to-chromium": "^1.4.164", @@ -3658,8 +4184,7 @@ "caniuse-lite": { "version": "1.0.30001359", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001359.tgz", - "integrity": "sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==", - "dev": true + "integrity": "sha512-Xln/BAsPzEuiVLgJ2/45IaqD9jShtk3Y33anKb4+yLwQzws3+v6odKfpgES/cDEaZMLzSChpIGdbOYtH9MyuHw==" }, "chalk": { "version": "4.1.2", @@ -3689,23 +4214,17 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "convert-source-map": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, "requires": { "safe-buffer": "~5.1.1" } }, - "core-js-pure": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.16.2.tgz", - "integrity": "sha512-oxKe64UH049mJqrKkynWp6Vu0Rlm/BTXO/bJZuN2mmR3RtOFNepLlSWDd1eo16PzHpQAoNG97rLU1V/YxesJjw==", - "dev": true - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -3717,18 +4236,42 @@ } }, "damerau-levenshtein": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.7.tgz", - "integrity": "sha512-VvdQIPGdWP0SqFXghj79Wf/5LArmreyMsGLa6FG6iC4t3j7j5s71TrwWmT/4akbDQIqjfACkLZmjXhA7g2oUZw==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", "dev": true, "requires": { - "ms": "2.1.2" + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" } }, "deep-is": { @@ -3738,12 +4281,13 @@ "dev": true }, "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "dev": true, "requires": { - "object-keys": "^1.0.12" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" } }, "dir-glob": { @@ -3767,35 +4311,82 @@ "electron-to-chromium": { "version": "1.4.170", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.170.tgz", - "integrity": "sha512-rZ8PZLhK4ORPjFqLp9aqC4/S1j4qWFsPPz13xmWdrbBkU/LlxMcok+f+6f8YnQ57MiZwKtOaW15biZZsY5Igvw==", - "dev": true + "integrity": "sha512-rZ8PZLhK4ORPjFqLp9aqC4/S1j4qWFsPPz13xmWdrbBkU/LlxMcok+f+6f8YnQ57MiZwKtOaW15biZZsY5Igvw==" }, "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.0.tgz", + "integrity": "sha512-GUGtW7eXQay0c+PRq0sGIKSdaBorfVqsCMhGHo4elP7YVqZu9nCZS4UkK4gv71gOWNMra/PaSKD3ao1oWExO0g==", "dev": true, "requires": { "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.0", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.3", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.4", + "is-array-buffer": "^3.0.0", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", + "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.2", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + } + }, + "es-get-iterator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + } + }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" } }, "es-to-primitive": { @@ -3812,8 +4403,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-string-regexp": { "version": "4.0.0", @@ -3822,13 +4412,15 @@ "dev": true }, "eslint": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.18.0.tgz", - "integrity": "sha512-As1EfFMVk7Xc6/CvhssHUjsAQSkpfXvUGMFC3ce8JDe6WvqCgRrLOBQbVpsBFr1X1V+RACOadnzVvcUS5ni2bA==", + "version": "8.31.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.31.0.tgz", + "integrity": "sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.3.0", - "@humanwhocodes/config-array": "^0.9.2", + "@eslint/eslintrc": "^1.4.1", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -3838,18 +4430,21 @@ "eslint-scope": "^7.1.1", "eslint-utils": "^3.0.0", "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", + "espree": "^9.4.0", "esquery": "^1.4.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.15.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -3860,8 +4455,7 @@ "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" + "text-table": "^0.2.0" }, "dependencies": { "eslint-scope": { @@ -3891,28 +4485,39 @@ } } }, + "eslint-config-prettier": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", + "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", + "dev": true, + "requires": {} + }, "eslint-plugin-eslint-custom-rules": { "version": "file:eslint-custom-rules", "requires": {} }, "eslint-plugin-jsx-a11y": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz", - "integrity": "sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.0.tgz", + "integrity": "sha512-EGGRKhzejSzXKtjmEjWNtr4SK/DkMkSzkBH7g7e7moBDXZXrqaUIxkmD7uF93upMysc4dKYEJwupu7Dff+ShwA==", "dev": true, "requires": { - "@babel/runtime": "^7.16.3", - "aria-query": "^4.2.2", - "array-includes": "^3.1.4", + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", "ast-types-flow": "^0.0.7", - "axe-core": "^4.3.5", - "axobject-query": "^2.2.0", - "damerau-levenshtein": "^1.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "has": "^1.0.3", - "jsx-ast-utils": "^3.2.1", - "language-tags": "^1.0.5", - "minimatch": "^3.0.4" + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" }, "dependencies": { "emoji-regex": { @@ -3920,6 +4525,12 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -3964,12 +4575,12 @@ "dev": true }, "espree": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", - "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", + "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", "dev": true, "requires": { - "acorn": "^8.7.1", + "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.3.0" } @@ -4043,9 +4654,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -4068,9 +4679,9 @@ "dev": true }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -4094,6 +4705,16 @@ "to-regex-range": "^5.0.1" } }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, "flat-cache": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", @@ -4110,10 +4731,20 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "function-bind": { "version": "1.1.1", @@ -4121,27 +4752,38 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", + "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.3" } }, "get-stream": { @@ -4183,14 +4825,23 @@ } }, "globals": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", - "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "version": "13.19.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", + "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", "dev": true, "requires": { "type-fest": "^0.20.2" } }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, "globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -4205,6 +4856,21 @@ "slash": "^3.0.0" } }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -4215,9 +4881,9 @@ } }, "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true }, "has-flag": { @@ -4226,10 +4892,25 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true + }, "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "dev": true }, "has-tostringtag": { @@ -4247,9 +4928,9 @@ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" }, "husky": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz", - "integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true }, "ignore": { @@ -4278,6 +4959,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -4286,19 +4968,41 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz", + "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==", "dev": true, "requires": { - "get-intrinsic": "^1.1.0", + "get-intrinsic": "^1.1.3", "has": "^1.0.3", "side-channel": "^1.0.4" } }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-array-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", + "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-typed-array": "^1.1.10" + } + }, "is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -4319,9 +5023,9 @@ } }, "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true }, "is-date-object": { @@ -4348,6 +5052,12 @@ "is-extglob": "^2.1.1" } }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true + }, "is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -4361,14 +5071,20 @@ "dev": true }, "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "requires": { "has-tostringtag": "^1.0.0" } }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -4379,12 +5095,21 @@ "has-tostringtag": "^1.0.0" } }, - "is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", "dev": true }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4408,6 +5133,25 @@ "has-symbols": "^1.0.2" } }, + "is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -4417,6 +5161,22 @@ "call-bind": "^1.0.2" } }, + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4425,14 +5185,18 @@ "javascript-natural-sort": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", - "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, + "js-sdsl": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", + "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", "dev": true }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "4.1.0", @@ -4446,8 +5210,7 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json-schema-traverse": { "version": "0.4.1", @@ -4464,17 +5227,16 @@ "json5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, "jsx-ast-utils": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz", - "integrity": "sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", "dev": true, "requires": { - "array-includes": "^3.1.3", - "object.assign": "^4.1.2" + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" } }, "language-subtag-registry": { @@ -4502,11 +5264,24 @@ "type-check": "~0.4.0" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.clone": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clone/-/lodash.clone-4.5.0.tgz", + "integrity": "sha512-GhrVeweiTD6uTmmn5hV/lzgCQhccwReIVRLHp7LT4SopOjqEZ5BbX8b5WWEtAKasjmy8hR7ZPwsYlxRCku5odg==" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" }, "lodash.merge": { "version": "4.6.2", @@ -4524,9 +5299,9 @@ } }, "macos-release": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.0.1.tgz", - "integrity": "sha512-3l6OrhdDg2H2SigtuN3jBh+5dRJRWxNKuJTPBbGeNJTsmt/pj9PO25wYaNb05NuNmAsl435j4rDP6rgNXz7s7g==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-3.1.0.tgz", + "integrity": "sha512-/M/R0gCDgM+Cv1IuBG1XGdfTFnMEG6PZeT+KGWHO/OG+imqmaD9CH5vHBTycEM3+Kc4uG2Il+tFAuUWLqQOeUA==" }, "merge-stream": { "version": "2.0.0", @@ -4558,6 +5333,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4565,8 +5341,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "natural-compare": { "version": "1.4.0", @@ -4574,11 +5349,16 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node-releases": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", - "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", - "dev": true + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==" }, "npm-run-path": { "version": "4.0.1", @@ -4589,11 +5369,21 @@ } }, "object-inspect": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz", - "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", "dev": true }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -4601,21 +5391,44 @@ "dev": true }, "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, + "object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -4643,14 +5456,32 @@ } }, "os-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.0.1.tgz", - "integrity": "sha512-0EQpaHUHq7olp2/YFUr+0vZi9tMpDTblHGz+Ch5RntKxiRXOAY0JOz1UlxhSjMSksHvkm13eD6elJj3M8Ht/kw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-5.1.0.tgz", + "integrity": "sha512-YEIoAnM6zFmzw3PQ201gCVCIWbXNyKObGlVvpAVvraAeOHnlYVKFssbA/riRX5R40WA6kKrZ7Dr7dWzO3nKSeQ==", "requires": { - "macos-release": "^3.0.1", + "macos-release": "^3.1.0", "windows-release": "^5.0.1" } }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4660,10 +5491,17 @@ "callsites": "^3.0.0" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "3.1.1", @@ -4679,8 +5517,7 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { "version": "2.3.1", @@ -4695,15 +5532,14 @@ "dev": true }, "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", - "dev": true + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.2.tgz", + "integrity": "sha512-BtRV9BcncDyI2tsuS19zzhzoxD8Dh8LiCx7j7tHzrkz8GFXAexeWFdi22mjE1d16dftH2qNaytVxqiRTGlMfpw==" }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz", + "integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==", "dev": true }, "queue-microtask": { @@ -4713,11 +5549,22 @@ "dev": true }, "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "dev": true }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -4757,8 +5604,18 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } }, "semver": { "version": "7.3.7", @@ -4805,23 +5662,25 @@ "dev": true }, "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" } }, "strip-ansi": { @@ -4862,8 +5721,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" }, "to-regex-range": { "version": "5.0.1", @@ -4904,21 +5762,32 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true }, "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, @@ -4926,7 +5795,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz", "integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==", - "dev": true, "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -4941,12 +5809,6 @@ "punycode": "^2.1.0" } }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4968,6 +5830,32 @@ "is-symbol": "^1.0.3" } }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + } + }, "windows-release": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-5.0.1.tgz", @@ -4985,13 +5873,20 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index ed1f3ac1a..fbf7fea35 100644 --- a/package.json +++ b/package.json @@ -4,22 +4,23 @@ "description": "", "private": true, "dependencies": { - "@next/eslint-plugin-next": "12.2.2", - "@types/mime-types": "^2.1.1", - "@types/node": "^18.0.0", - "os-name": "^5.0.1" + "@ianvs/prettier-plugin-sort-imports": "^3.7.1", + "os-name": "^5.1.0" }, "devDependencies": { - "@ianvs/prettier-plugin-sort-imports": "^3.4.2", - "@typescript-eslint/eslint-plugin": "^5.19.0", - "@typescript-eslint/parser": "^5.19.0", - "eslint": "^8.13.0", + "@next/eslint-plugin-next": "12.2.2", + "@types/mime-types": "^2.1.1", + "@types/node": "^18.11.18", + "@typescript-eslint/eslint-plugin": "^5.48.1", + "@typescript-eslint/parser": "^5.48.1", + "eslint": "^8.31.0", + "eslint-config-prettier": "^8.6.0", "eslint-plugin-eslint-custom-rules": "file:eslint-custom-rules", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react-hooks": "^4.4.0", - "husky": "^8.0.1", - "prettier": "^2.6.2", - "typescript": "^4.6.3" + "eslint-plugin-jsx-a11y": "^6.7.0", + "eslint-plugin-react-hooks": "^4.6.0", + "husky": "^8.0.3", + "prettier": "^2.8.2", + "typescript": "^4.9.4" }, "scripts": { "prettier": "prettier --write \"**/*.js\" \"**/*.ts\" \"**/*.tsx\" \"**/*.d.ts\" --cache", diff --git a/shibbo/src/server.ts b/shibbo/src/server.ts index 72276580a..27b7e25ca 100644 --- a/shibbo/src/server.ts +++ b/shibbo/src/server.ts @@ -22,7 +22,7 @@ const SHIBBOLETH_HEADERS = [ "schachomeorganization", ] as const -const defaultHeaders: Record = { +const defaultHeaders: Record<(typeof SHIBBOLETH_HEADERS)[number], string> = { displayname: "kissa kissanen", schachomeorganization: "yliopisto.fi", schacpersonaluniquecode: diff --git a/tsconfig.json b/tsconfig.json index 2c63c0851..9647394af 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,2 +1,5 @@ { + "compilerOptions": { + "strictNullChecks": true + } }