diff --git a/src/api/index.ts b/src/api/index.ts index bb6e78ac..483bcce4 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -62,6 +62,7 @@ import { docsHtml, securitySchemes } from "./docs.js"; import syncIdentityPlugin from "./routes/syncIdentity.js"; import { createRedisModule } from "./redis.js"; import userRoute from "./routes/user.js"; +import rsvpRoutes from "./routes/rsvp.js"; /** END ROUTES */ export const instanceId = randomUUID(); @@ -377,6 +378,9 @@ Otherwise, email [infra@acm.illinois.edu](mailto:infra@acm.illinois.edu) for sup api.register(apiKeyRoute, { prefix: "/apiKey" }); api.register(clearSessionRoute, { prefix: "/clearSession" }); api.register(userRoute, { prefix: "/users" }); + if (app.runEnvironment === "dev") { + api.register(rsvpRoutes, { prefix: "/rsvp" }); + } if (app.runEnvironment === "dev") { api.register(vendingPlugin, { prefix: "/vending" }); } diff --git a/src/api/routes/rsvp.ts b/src/api/routes/rsvp.ts new file mode 100644 index 00000000..b1ebb107 --- /dev/null +++ b/src/api/routes/rsvp.ts @@ -0,0 +1,126 @@ +import { FastifyPluginAsync } from "fastify"; +import rateLimiter from "api/plugins/rateLimiter.js"; +import { withRoles, withTags } from "api/components/index.js"; +import { QueryCommand, PutItemCommand } from "@aws-sdk/client-dynamodb"; +import { unmarshall, marshall } from "@aws-sdk/util-dynamodb"; +import { + DatabaseFetchError, + UnauthenticatedError, + UnauthorizedError, + ValidationError, +} from "common/errors/index.js"; +import * as z from "zod/v4"; +import { verifyUiucAccessToken } from "api/functions/uin.js"; +import { checkPaidMembership } from "api/functions/membership.js"; +import { FastifyZodOpenApiTypeProvider } from "fastify-zod-openapi"; +import { genericConfig } from "common/config.js"; +import { AppRoles } from "common/roles.js"; + +const rsvpRoutes: FastifyPluginAsync = async (fastify, _options) => { + await fastify.register(rateLimiter, { + limit: 30, + duration: 30, + rateLimitIdentifier: "rsvp", + }); + fastify.withTypeProvider().post( + "/:orgId/event/:eventId", + { + schema: withTags(["RSVP"], { + summary: "Submit an RSVP for an event.", + params: z.object({ + eventId: z.string().min(1).meta({ + description: "The previously-created event ID in the events API.", + }), + orgId: z.string().min(1).meta({ + description: "The organization ID the event belongs to.", + }), + }), + headers: z.object({ + "x-uiuc-token": z.jwt().min(1).meta({ + description: + "An access token for the user in the UIUC Entra ID tenant.", + }), + }), + }), + }, + async (request, reply) => { + const accessToken = request.headers["x-uiuc-token"]; + const verifiedData = await verifyUiucAccessToken({ + accessToken, + logger: request.log, + }); + const { userPrincipalName: upn, givenName, surname } = verifiedData; + const netId = upn.replace("@illinois.edu", ""); + if (netId.includes("@")) { + request.log.error( + `Found UPN ${upn} which cannot be turned into NetID via simple replacement.`, + ); + throw new ValidationError({ + message: "ID token could not be parsed.", + }); + } + const isPaidMember = await checkPaidMembership({ + netId, + dynamoClient: fastify.dynamoClient, + redisClient: fastify.redisClient, + logger: request.log, + }); + const entry = { + partitionKey: `${request.params.eventId}#${upn}`, + eventId: request.params.eventId, + userId: upn, + isPaidMember, + createdAt: "", + }; + const putCommand = new PutItemCommand({ + TableName: genericConfig.RSVPDynamoTableName, + Item: marshall(entry), + }); + await fastify.dynamoClient.send(putCommand); + return reply.status(201).send(entry); + }, + ); + fastify.withTypeProvider().get( + "/:orgId/event/:eventId", + { + schema: withRoles( + [AppRoles.VIEW_RSVPS], + withTags(["RSVP"], { + summary: "Get all RSVPs for an event.", + params: z.object({ + eventId: z.string().min(1).meta({ + description: "The previously-created event ID in the events API.", + }), + orgId: z.string().min(1).meta({ + description: "The organization ID the event belongs to.", + }), + }), + }), + ), + onRequest: fastify.authorizeFromSchema, + }, + async (request, reply) => { + const command = new QueryCommand({ + TableName: genericConfig.RSVPDynamoTableName, + IndexName: "EventIdIndex", + KeyConditionExpression: "eventId = :eid", + ExpressionAttributeValues: { + ":eid": { S: request.params.eventId }, + }, + }); + const response = await fastify.dynamoClient.send(command); + if (!response || !response.Items) { + throw new DatabaseFetchError({ + message: "Failed to get all member lists.", + }); + } + const rsvps = response.Items.map((x) => unmarshall(x)); + const uniqueRsvps = [ + ...new Map(rsvps.map((item) => [item.userId, item])).values(), + ]; + return reply.send(uniqueRsvps); + }, + ); +}; + +export default rsvpRoutes; diff --git a/src/common/config.ts b/src/common/config.ts index 1b1fe59e..0f093ffc 100644 --- a/src/common/config.ts +++ b/src/common/config.ts @@ -38,6 +38,7 @@ export type ConfigType = { export type GenericConfigType = { EventsDynamoTableName: string; + RSVPDynamoTableName: string; CacheDynamoTableName: string; LinkryDynamoTableName: string; StripeLinksDynamoTableName: string; @@ -84,6 +85,7 @@ export const commChairsGroupId = "105e7d32-7289-435e-a67a-552c7f215507"; const genericConfig: GenericConfigType = { EventsDynamoTableName: "infra-core-api-events", + RSVPDynamoTableName: "infra-core-api-events-rsvp", StripeLinksDynamoTableName: "infra-core-api-stripe-links", StripePaymentsDynamoTableName: "infra-core-api-stripe-payments", CacheDynamoTableName: "infra-core-api-cache", diff --git a/src/common/roles.ts b/src/common/roles.ts index b6417017..72564395 100644 --- a/src/common/roles.ts +++ b/src/common/roles.ts @@ -7,6 +7,8 @@ export const META_ROLE_PREFIX = "__metaRole:" export enum BaseRoles { EVENTS_MANAGER = "manage:events", + RSVPS_MANAGER = "manage:rsvps", + VIEW_RSVPS = "view:rsvps", TICKETS_SCANNER = "scan:tickets", TICKETS_MANAGER = "manage:tickets", IAM_ADMIN = "admin:iam", @@ -47,6 +49,8 @@ export const AppRoleHumanMapper: Record = { [AppRoles.EVENTS_MANAGER]: "Events Manager", [AppRoles.TICKETS_SCANNER]: "Tickets Scanner", [AppRoles.TICKETS_MANAGER]: "Tickets Manager", + [AppRoles.RSVPS_MANAGER]: "RSVPs Manager", + [AppRoles.VIEW_RSVPS]: "RSVPs Viewer", [AppRoles.IAM_ADMIN]: "IAM Admin", [AppRoles.IAM_INVITE_ONLY]: "IAM Inviter", [AppRoles.LINKS_MANAGER]: "Links Manager", diff --git a/src/common/types/rsvp.ts b/src/common/types/rsvp.ts new file mode 100644 index 00000000..51f13c53 --- /dev/null +++ b/src/common/types/rsvp.ts @@ -0,0 +1,8 @@ +import * as z from "zod/v4"; + +export const rsvpItemSchema = z.object({ + eventId: z.string(), + userId: z.string(), + isPaidMember: z.boolean(), + createdAt: z.string(), +}); diff --git a/terraform/modules/dynamo/main.tf b/terraform/modules/dynamo/main.tf index d9a93076..3858a78d 100644 --- a/terraform/modules/dynamo/main.tf +++ b/terraform/modules/dynamo/main.tf @@ -567,3 +567,36 @@ resource "aws_dynamodb_table" "store_limits" { } } } + +resource "aws_dynamodb_table" "events_rsvp" { + region = "us-east-2" + billing_mode = "PAY_PER_REQUEST" + name = "${var.ProjectId}-events-rsvp" + deletion_protection_enabled = true + hash_key = "partitionKey" + point_in_time_recovery { + enabled = true + } + attribute { + name = "partitionKey" + type = "S" + } + attribute { + name = "eventId" + type = "S" + } + global_secondary_index { + name = "EventIdIndex" + hash_key = "eventId" + projection_type = "ALL" + } + stream_enabled = true + stream_view_type = "NEW_AND_OLD_IMAGES" + dynamic "replica" { + for_each = var.ReplicationRegions + content { + region_name = replica.value + deletion_protection_enabled = true + } + } +} diff --git a/tests/unit/rsvps.test.ts b/tests/unit/rsvps.test.ts new file mode 100644 index 00000000..1ff3cae6 --- /dev/null +++ b/tests/unit/rsvps.test.ts @@ -0,0 +1,157 @@ +import { expect, test, vi, describe, beforeEach } from "vitest"; +import { + DynamoDBClient, + PutItemCommand, + QueryCommand, +} from "@aws-sdk/client-dynamodb"; +import { marshall } from "@aws-sdk/util-dynamodb"; +import { mockClient } from "aws-sdk-client-mock"; +import init from "../../src/api/index.js"; +import { createJwt } from "./auth.test.js"; +import { testSecretObject } from "./secret.testdata.js"; +import { Redis } from "../../src/api/types.js"; +import { FastifyBaseLogger } from "fastify"; + +const DUMMY_JWT = + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"; + +vi.mock("../../src/api/functions/uin.js", async () => { + const actual = await vi.importActual("../../src/api/functions/uin.js"); + return { + ...actual, + verifyUiucAccessToken: vi + .fn() + .mockImplementation( + async ({ + token, + logger, + }: { + token: string; + logger: FastifyBaseLogger; + }) => { + if (token === DUMMY_JWT) { + console.log("DUMMY_JWT matched in mock implementation"); + } + return { + userPrincipalName: "jd3@illinois.edu", + givenName: "John", + surname: "Doe", + mail: "johndoe@gmail.com", + }; + }, + ), + }; +}); + +vi.mock("../../src/api/functions/membership.js", async () => { + const actual = await vi.importActual("../../src/api/functions/membership.js"); + return { + ...actual, + checkPaidMembership: vi + .fn() + .mockImplementation( + async ({ + netId, + redisClient, + dynamoClient, + logger, + }: { + netId: string; + redisClient: Redis; + dynamoClient: DynamoDBClient; + logger: FastifyBaseLogger; + }) => { + if (netId === "jd3") { + return true; + } + return false; + }, + ), + }; +}); + +const ddbMock = mockClient(DynamoDBClient); +const jwt_secret = testSecretObject["jwt_key"]; +vi.stubEnv("JwtSigningKey", jwt_secret); + +const app = await init(); + +describe("RSVP API tests", () => { + beforeEach(() => { + ddbMock.reset(); + vi.clearAllMocks(); + }); + + test("Test posting an RSVP for an event", async () => { + ddbMock.on(PutItemCommand).resolves({}); + + const testJwt = createJwt(); + const mockUpn = "jd3@illinois.edu"; + const eventId = "Make Your Own Database"; + const orgId = "SIGDatabase"; + + const response = await app.inject({ + method: "POST", + url: `/api/v1/rsvp/${orgId}/event/${encodeURIComponent(eventId)}`, + headers: { + Authorization: `Bearer ${testJwt}`, + "x-uiuc-token": DUMMY_JWT, + }, + }); + + if (response.statusCode !== 201) { + console.log("Test Failed Response:", response.body); + } + + expect(response.statusCode).toBe(201); + + const body = JSON.parse(response.body); + expect(body.userId).toBe(mockUpn); + expect(body.eventId).toBe(eventId); + expect(body.isPaidMember).toBe(true); + expect(body.partitionKey).toBe(`${eventId}#${mockUpn}`); + + expect(ddbMock.calls()).toHaveLength(1); + const putItemInput = ddbMock.call(0).args[0].input as any; + expect(putItemInput.TableName).toBe("infra-core-api-events-rsvp"); + }); + + test("Test getting RSVPs for an event (Mocking Query Response)", async () => { + const eventId = "Make Your Own Database"; + const orgId = "SIGDatabase"; + const mockRsvps = [ + { + eventId, + userId: "user1@illinois.edu", + isPaidMember: true, + createdAt: "2023-01-01", + }, + { + eventId, + userId: "user2@illinois.edu", + isPaidMember: false, + createdAt: "2023-01-02", + }, + ]; + ddbMock.on(QueryCommand).resolves({ + Items: mockRsvps.map((item) => marshall(item)), + }); + + const adminJwt = await createJwt(); + + const response = await app.inject({ + method: "GET", + url: `/api/v1/rsvp/${orgId}/event/${encodeURIComponent(eventId)}`, + headers: { + Authorization: `Bearer ${adminJwt}`, + }, + }); + + expect(response.statusCode).toBe(200); + const body = JSON.parse(response.body); + + expect(body).toHaveLength(2); + expect(body[0].userId).toBe("user1@illinois.edu"); + expect(body[1].userId).toBe("user2@illinois.edu"); + }); +}); diff --git a/yarn.lock b/yarn.lock index b572b07a..39f4a1e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1989,7 +1989,7 @@ resolved "https://registry.yarnpkg.com/@napi-rs/canvas-win32-x64-msvc/-/canvas-win32-x64-msvc-0.1.81.tgz#e76784880f26d48f4863d73c9891c53f161ffe6e" integrity sha512-57ryVbhm/z7RE9/UVcS7mrLPdlayLesy+9U0Uf6epCoeSGrs99tfieCcgZWFbIgmByQ1AZnNtFI2N6huqDLlWQ== -"@napi-rs/canvas@^0.1.65", "@napi-rs/canvas@^0.1.80", "@napi-rs/canvas@^0.1.81": +"@napi-rs/canvas@^0.1.65": version "0.1.81" resolved "https://registry.yarnpkg.com/@napi-rs/canvas/-/canvas-0.1.81.tgz#4cb1556171a64480e52d2a3766aa5413bfc4a9b1" integrity sha512-ReCjd5SYI/UKx/olaQLC4GtN6wUQGjlgHXs1lvUvWGXfBMR3Fxnik3cL+OxKN5ithNdoU0/GlCrdKcQDFh2XKQ== @@ -4575,7 +4575,7 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -bl@^4.0.2, bl@^4.0.3: +bl@^4.0.2: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== @@ -4716,14 +4716,6 @@ caniuse-lite@^1.0.30001726: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz#a15bd87d5a4bf01f6b6f70ae7c97fdfd28b5ae47" integrity sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw== -canvas@^3.0.0-rc2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/canvas/-/canvas-3.2.0.tgz#877c51aabdb99cbb5b2b378138a6cdd681e9d390" - integrity sha512-jk0GxrLtUEmW/TmFsk2WghvgHe8B0pxGilqCL21y8lHkPUGa6FTsnCNtHPOzT8O3y+N+m3espawV80bbBlgfTA== - dependencies: - node-addon-api "^7.0.0" - prebuild-install "^7.1.3" - chai@^5.1.1, chai@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05" @@ -4785,11 +4777,6 @@ chokidar@^3.5.2, chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" -chownr@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" - integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== - cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -5107,13 +5094,6 @@ decimal.js@^10.5.0: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.5.0.tgz#0f371c7cf6c4898ce0afb09836db73cd82010f22" integrity sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw== -decompress-response@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" - integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== - dependencies: - mimic-response "^3.1.0" - deep-eql@^5.0.1: version "5.0.2" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" @@ -5143,11 +5123,6 @@ deep-equal@^2.0.5: which-collection "^1.0.1" which-typed-array "^1.1.13" -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -5201,11 +5176,6 @@ dequal@^2.0.2, dequal@^2.0.3: resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== -detect-libc@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" - integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== - detect-node-es@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" @@ -6027,11 +5997,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - expect-type@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.1.tgz#af76d8b357cf5fa76c41c09dafb79c549e75f71f" @@ -6373,11 +6338,6 @@ formidable@^3.5.4: dezalgo "^1.0.4" once "^1.4.0" -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - fs-extra@^10.0.1: version "10.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" @@ -6484,11 +6444,6 @@ get-tsconfig@^4.10.1, get-tsconfig@^4.7.5: dependencies: resolve-pkg-maps "^1.0.0" -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== - glob-parent@^5.0.0, glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -6841,7 +6796,7 @@ inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, i resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@^1.3.5, ini@~1.3.0: +ini@^1.3.5: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== @@ -7821,11 +7776,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" - integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== - min-indent@^1.0.0, min-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -7852,7 +7802,7 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" -minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -7862,11 +7812,6 @@ minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1. resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== -mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" - integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== - mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -7952,11 +7897,6 @@ nanoid@^3.3.11: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== -napi-build-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e" - integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== - napi-postinstall@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/napi-postinstall/-/napi-postinstall-0.3.0.tgz#888e51d1fb500e86dcf6ace1baccdbb377e654ce" @@ -7988,18 +7928,6 @@ nise@^6.0.0: just-extend "^6.2.0" path-to-regexp "^8.1.0" -node-abi@^3.3.0: - version "3.80.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.80.0.tgz#d7390951f27caa129cceeec01e1c20fc9f07581c" - integrity sha512-LyPuZJcI9HVwzXK1GPxWNzrr+vr8Hp/3UqlmWxxh8p54U1ZbclOqbSog9lWHaCX+dBaiGi6n/hIX+mKu74GmPA== - dependencies: - semver "^7.3.5" - -node-addon-api@^7.0.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" - integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== - node-addon-api@^8.5.0: version "8.5.0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.5.0.tgz#c91b2d7682fa457d2e1c388150f0dff9aafb8f3f" @@ -8385,11 +8313,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -path2d@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/path2d/-/path2d-0.2.2.tgz#cc85d61ed7827e7863a2ee36713d4b5315a3d85d" - integrity sha512-+vnG6S4dYcYxZd+CZxzXCNKdELYZSKfohrk98yajCo1PtRoDgCTrrwOvK1GT0UoAdVszagDVllQc0U1vaX4NUQ== - pathe@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" @@ -8400,35 +8323,13 @@ pathval@^2.0.0: resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.1.tgz#8855c5a2899af072d6ac05d11e46045ad0dc605d" integrity sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ== -pdfjs-dist@4.8.69: - version "4.8.69" - resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-4.8.69.tgz#61ea5d66863d49b40e5eacbd4070341175bdda2e" - integrity sha512-IHZsA4T7YElCKNNXtiLgqScw4zPd3pG9do8UrznC757gMd7UPeHSL2qwNNMJo4r79fl8oj1Xx+1nh2YkzdMpLQ== - optionalDependencies: - canvas "^3.0.0-rc2" - path2d "^0.2.1" - -pdfjs-dist@5.4.296: - version "5.4.296" - resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-5.4.296.tgz#b1aa7ded8828f29537bc7cc99c1343c8b3a5d2d6" - integrity sha512-DlOzet0HO7OEnmUmB6wWGJrrdvbyJKftI1bhMitK7O2N8W2gc757yyYBbINy9IDafXAV9wmKr9t7xsTaNKRG5Q== - optionalDependencies: - "@napi-rs/canvas" "^0.1.80" - -pdfjs-dist@^4.6.82: +pdfjs-dist@4.8.69, pdfjs-dist@5.4.296, pdfjs-dist@^4.6.82, pdfjs-dist@^4.8.69, pdfjs-dist@^5.4.394: version "4.10.38" resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-4.10.38.tgz#3ee698003790dc266cc8b55c0e662ccb9ae18f53" integrity sha512-/Y3fcFrXEAsMjJXeL9J8+ZG9U01LbuWaYypvDW2ycW1jL269L3js3DVBjDJ0Up9Np1uqDXsDrRihHANhZOlwdQ== optionalDependencies: "@napi-rs/canvas" "^0.1.65" -pdfjs-dist@^5.4.394: - version "5.4.394" - resolved "https://registry.yarnpkg.com/pdfjs-dist/-/pdfjs-dist-5.4.394.tgz#48697151afce097132673883a55bede103ded6e4" - integrity sha512-9ariAYGqUJzx+V/1W4jHyiyCep6IZALmDzoaTLZ6VNu8q9LWi1/ukhzHgE2Xsx96AZi0mbZuK4/ttIbqSbLypg== - optionalDependencies: - "@napi-rs/canvas" "^0.1.81" - picocolors@1.1.1, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -8624,24 +8525,6 @@ postcss@^8.3.11, postcss@^8.5.3, postcss@^8.5.6: picocolors "^1.1.1" source-map-js "^1.2.1" -prebuild-install@^7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" - integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== - dependencies: - detect-libc "^2.0.0" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.3" - mkdirp-classic "^0.5.3" - napi-build-utils "^2.0.0" - node-abi "^3.3.0" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^4.0.0" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -8766,16 +8649,6 @@ raw-body@^3.0.0: iconv-lite "0.6.3" unpipe "1.0.0" -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-docgen-typescript@^2.2.2: version "2.4.0" resolved "https://registry.yarnpkg.com/react-docgen-typescript/-/react-docgen-typescript-2.4.0.tgz#033428b4a6a639d050ac8baf2a5195c596521713" @@ -9306,7 +9179,7 @@ semver@^6.1.2, semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.7.1: +semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.7.1: version "7.7.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== @@ -9441,20 +9314,6 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -simple-concat@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" - integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== - -simple-get@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" - integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== - dependencies: - decompress-response "^6.0.0" - once "^1.3.1" - simple-concat "^1.0.0" - simple-update-notifier@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" @@ -9790,11 +9649,6 @@ strip-json-comments@^5.0.2: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.2.tgz#14a76abd63b84a6d2419d14f26a0281d0cf6ea46" integrity sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g== -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - strip-literal@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-3.0.0.tgz#ce9c452a91a0af2876ed1ae4e583539a353df3fc" @@ -10006,27 +9860,6 @@ table@^6.9.0: string-width "^4.2.3" strip-ansi "^6.0.1" -tar-fs@^2.0.0: - version "2.1.4" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930" - integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ== - dependencies: - chownr "^1.1.1" - mkdirp-classic "^0.5.2" - pump "^3.0.0" - tar-stream "^2.1.4" - -tar-stream@^2.1.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" - integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== - dependencies: - bl "^4.0.3" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - test-exclude@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-7.0.1.tgz#20b3ba4906ac20994e275bbcafd68d510264c2a2" @@ -10230,13 +10063,6 @@ tsx@^4.20.4: optionalDependencies: fsevents "~2.3.3" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== - dependencies: - safe-buffer "^5.0.1" - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"