diff --git a/api.planx.uk/admin/feedback/downloadFeedbackCSV.ts b/api.planx.uk/admin/feedback/downloadFeedbackCSV.ts index 316af72c61..6836fb37a8 100644 --- a/api.planx.uk/admin/feedback/downloadFeedbackCSV.ts +++ b/api.planx.uk/admin/feedback/downloadFeedbackCSV.ts @@ -62,7 +62,7 @@ type ParsedFeedback = Feedback & { * tags: * - admin * security: - * - userJWT: [] + * - bearerAuth: [] */ export const downloadFeedbackCSV = async ( req: Request, diff --git a/api.planx.uk/admin/session/bops.ts b/api.planx.uk/admin/session/bops.ts index 1bf26828be..74aa8feb0a 100644 --- a/api.planx.uk/admin/session/bops.ts +++ b/api.planx.uk/admin/session/bops.ts @@ -1,5 +1,5 @@ import { Request, Response, NextFunction } from "express"; -import { $admin } from "../../client"; +import { getClient } from "../../client"; /** * @swagger @@ -12,7 +12,7 @@ import { $admin } from "../../client"; * parameters: * - $ref: '#/components/parameters/sessionId' * security: - * - userJWT: [] + * - bearerAuth: [] */ export const getBOPSPayload = async ( req: Request, @@ -20,7 +20,8 @@ export const getBOPSPayload = async ( next: NextFunction, ) => { try { - const { exportData } = await $admin.export.bopsPayload( + const $client = getClient(); + const { exportData } = await $client.export.bopsPayload( req.params.sessionId, ); res.set("content-type", "application/json"); diff --git a/api.planx.uk/admin/session/csv.ts b/api.planx.uk/admin/session/csv.ts index e99659678f..06d0bb00be 100644 --- a/api.planx.uk/admin/session/csv.ts +++ b/api.planx.uk/admin/session/csv.ts @@ -1,6 +1,6 @@ import { stringify } from "csv-stringify"; import { NextFunction, Request, Response } from "express"; -import { $admin } from "../../client"; +import { getClient } from "../../client"; /** * @swagger @@ -18,7 +18,7 @@ import { $admin } from "../../client"; * required: false * description: If a CSV file should be downloaded, or its raw data returned * security: - * - userJWT: [] + * - bearerAuth: [] */ export async function getCSVData( req: Request, @@ -26,7 +26,8 @@ export async function getCSVData( next: NextFunction, ) { try { - const { responses } = await $admin.export.csvData(req.params.sessionId); + const $client = getClient(); + const { responses } = await $client.export.csvData(req.params.sessionId); if (req.query?.download) { stringify(responses, { @@ -61,7 +62,7 @@ export async function getCSVData( * required: false * description: If a CSV file should be downloaded, or its raw data returned * security: - * - userJWT: [] + * - bearerAuth: [] */ export async function getRedactedCSVData( req: Request, @@ -69,7 +70,8 @@ export async function getRedactedCSVData( next: NextFunction, ) { try { - const { redactedResponses } = await $admin.export.csvData( + const $client = getClient(); + const { redactedResponses } = await $client.export.csvData( req.params.sessionId, ); diff --git a/api.planx.uk/admin/session/html.ts b/api.planx.uk/admin/session/html.ts index 01a0f89b7a..52560d79da 100644 --- a/api.planx.uk/admin/session/html.ts +++ b/api.planx.uk/admin/session/html.ts @@ -1,5 +1,5 @@ import { generateApplicationHTML } from "@opensystemslab/planx-core"; -import { $admin } from "../../client"; +import { getClient } from "../../client"; import type { RequestHandler } from "express"; import type { PlanXExportData } from "@opensystemslab/planx-core/types"; @@ -16,14 +16,15 @@ type HTMLExportHandler = RequestHandler<{ sessionId: string }, string>; * parameters: * - $ref: '#/components/parameters/sessionId' * security: - * - userJWT: [] + * - bearerAuth: [] */ export const getHTMLExport: HTMLExportHandler = async (req, res, next) => { try { - const session = await $admin.session.find(req.params.sessionId); + const $client = getClient(); + const session = await $client.session.find(req.params.sessionId); if (!session) throw Error(`Unable to find session ${req.params.sessionId}`); - const { responses } = await $admin.export.csvData(req.params.sessionId); + const { responses } = await $client.export.csvData(req.params.sessionId); const boundingBox = session.data.passport.data["property.boundary.site.buffered"]; @@ -52,7 +53,7 @@ export const getHTMLExport: HTMLExportHandler = async (req, res, next) => { * parameters: * - $ref: '#/components/parameters/sessionId' * security: - * - userJWT: [] + * - bearerAuth: [] */ export const getRedactedHTMLExport: HTMLExportHandler = async ( req, @@ -60,10 +61,11 @@ export const getRedactedHTMLExport: HTMLExportHandler = async ( next, ) => { try { - const session = await $admin.session.find(req.params.sessionId); + const $client = getClient(); + const session = await $client.session.find(req.params.sessionId); if (!session) throw Error(`Unable to find session ${req.params.sessionId}`); - const { redactedResponses } = await $admin.export.csvData( + const { redactedResponses } = await $client.export.csvData( req.params.sessionId, ); const boundingBox = diff --git a/api.planx.uk/admin/session/oneAppXML.ts b/api.planx.uk/admin/session/oneAppXML.ts index d91e1897e7..2f95b144cc 100644 --- a/api.planx.uk/admin/session/oneAppXML.ts +++ b/api.planx.uk/admin/session/oneAppXML.ts @@ -13,7 +13,7 @@ import { adminGraphQLClient as client } from "../../hasura"; * parameters: * - $ref: '#/components/parameters/sessionId' * security: - * - userJWT: [] + * - bearerAuth: [] */ export const getOneAppXML = async ( req: Request, diff --git a/api.planx.uk/admin/session/summary.ts b/api.planx.uk/admin/session/summary.ts index 5e7949cd6e..d0975c9e0a 100644 --- a/api.planx.uk/admin/session/summary.ts +++ b/api.planx.uk/admin/session/summary.ts @@ -20,7 +20,7 @@ import { Breadcrumb, Flow, LowCalSession, Passport, Team } from "../../types"; * parameters: * - $ref: '#/components/parameters/sessionId' * security: - * - userJWT: [] + * - bearerAuth: [] */ export async function getSessionSummary( req: Request, diff --git a/api.planx.uk/admin/session/zip.ts b/api.planx.uk/admin/session/zip.ts index 25b9c9c1ed..e57179807f 100644 --- a/api.planx.uk/admin/session/zip.ts +++ b/api.planx.uk/admin/session/zip.ts @@ -17,7 +17,7 @@ import { buildSubmissionExportZip } from "../../send/exportZip"; * required: false * description: If the OneApp XML file should be included in the zip * security: - * - userJWT: [] + * - bearerAuth: [] */ export async function generateZip( req: Request, diff --git a/api.planx.uk/client/index.ts b/api.planx.uk/client/index.ts index e14bd8ac95..4a8e99fdb8 100644 --- a/api.planx.uk/client/index.ts +++ b/api.planx.uk/client/index.ts @@ -1,7 +1,13 @@ import { CoreDomainClient } from "@opensystemslab/planx-core"; +import { userContext } from "../modules/auth/middleware"; +import { ServerError } from "../errors"; + /** - * core doesn't expose a graphql interface like the graphql/hasura clients do - * instead, they encapsulates query and business logic to only expose declarative interfaces + * @deprecated This client's permissions set are higher than required. + * Should only be used by trusted service-to-service calls (e.g Hasura -> API). + * Calls made by users should be directed through $public or the role-scoped getClient(). + * + * Consider removing this and replacing with an "api" role using "backend-only" operations in Hasura */ export const $admin = new CoreDomainClient({ auth: { adminSecret: process.env.HASURA_GRAPHQL_ADMIN_SECRET! }, @@ -11,3 +17,26 @@ export const $admin = new CoreDomainClient({ export const $public = new CoreDomainClient({ targetURL: process.env.HASURA_GRAPHQL_URL!, }); + +/** + * Get a planx-core client with permissions scoped to the current user. + * This client instance ensures that all operations are restricted + * to the permissions of the user who initiated the request. + */ +export const getClient = () => { + const store = userContext.getStore(); + if (!store) + throw new ServerError({ + status: 500, + message: "Missing user context", + }); + + const client = new CoreDomainClient({ + targetURL: process.env.HASURA_GRAPHQL_URL!, + auth: { + jwt: store.user.jwt, + }, + }); + + return client; +}; diff --git a/api.planx.uk/editor/copyFlow.ts b/api.planx.uk/editor/copyFlow.ts index 2549625143..8f8e703e0c 100644 --- a/api.planx.uk/editor/copyFlow.ts +++ b/api.planx.uk/editor/copyFlow.ts @@ -1,6 +1,7 @@ import { Request, Response, NextFunction } from "express"; import { makeUniqueFlow, getFlowData, insertFlow } from "../helpers"; import { Flow } from "../types"; +import { userContext } from "../modules/auth/middleware"; const copyFlow = async ( req: Request, @@ -25,13 +26,15 @@ const copyFlow = async ( const shouldInsert = (req.body?.insert as boolean) || false; if (shouldInsert) { const newSlug = flow.slug + "-copy"; - const creatorId = parseInt(req.user!.sub!, 10); + const creatorId = userContext.getStore()?.user?.sub; + if (!creatorId) throw Error("User details missing from request"); + // Insert the flow and an associated operation await insertFlow( flow.team_id, newSlug, uniqueFlowData, - creatorId, + parseInt(creatorId), req.params.flowId, ); } diff --git a/api.planx.uk/editor/publish.ts b/api.planx.uk/editor/publish.ts index ed19f40ba1..1c81377389 100644 --- a/api.planx.uk/editor/publish.ts +++ b/api.planx.uk/editor/publish.ts @@ -5,6 +5,7 @@ import { dataMerged, getMostRecentPublishedFlow } from "../helpers"; import { gql } from "graphql-request"; import intersection from "lodash/intersection"; import { ComponentType } from "@opensystemslab/planx-core/types"; +import { userContext } from "../modules/auth/middleware"; const validateAndDiffFlow = async ( req: Request, @@ -73,6 +74,9 @@ const publishFlow = async ( const mostRecent = await getMostRecentPublishedFlow(req.params.flowId); const delta = jsondiffpatch.diff(mostRecent, flattenedFlow); + const userId = userContext.getStore()?.user?.sub; + if (!userId) throw Error("User details missing from request"); + if (delta) { const response = await adminClient.request( gql` @@ -101,7 +105,7 @@ const publishFlow = async ( { data: flattenedFlow, flow_id: req.params.flowId, - publisher_id: parseInt(req.user!.sub!, 10), + publisher_id: parseInt(userId), summary: req.query?.summary || null, }, ); diff --git a/api.planx.uk/inviteToPay/sendConfirmationEmail.ts b/api.planx.uk/inviteToPay/sendConfirmationEmail.ts index ea6e50c80c..42f5d93f44 100644 --- a/api.planx.uk/inviteToPay/sendConfirmationEmail.ts +++ b/api.planx.uk/inviteToPay/sendConfirmationEmail.ts @@ -1,4 +1,4 @@ -import { $admin } from "../client"; +import { $public, $admin } from "../client"; import { sendEmail } from "../notify"; import { gql } from "graphql-request"; import { convertSlugToName } from "../saveAndReturn/utils"; @@ -8,7 +8,7 @@ export async function sendAgentAndPayeeConfirmationEmail(sessionId: string) { const { personalisation, applicantEmail, payeeEmail, projectTypes } = await getDataForPayeeAndAgentEmails(sessionId); const projectType = projectTypes.length - ? await $admin.formatRawProjectTypes(projectTypes) + ? await $public.formatRawProjectTypes(projectTypes) : "Project type not submitted"; const config: AgentAndPayeeSubmissionNotifyConfig = { personalisation: { diff --git a/api.planx.uk/inviteToPay/sendPaymentEmail.ts b/api.planx.uk/inviteToPay/sendPaymentEmail.ts index d9b884f57b..96c6e31e99 100644 --- a/api.planx.uk/inviteToPay/sendPaymentEmail.ts +++ b/api.planx.uk/inviteToPay/sendPaymentEmail.ts @@ -8,7 +8,7 @@ import { Template, getClientForTemplate, sendEmail } from "../notify"; import { InviteToPayNotifyConfig } from "../types"; import { Team } from "../types"; import type { PaymentRequest } from "@opensystemslab/planx-core/types"; -import { $admin } from "../client"; +import { $public } from "../client"; interface SessionDetails { email: string; @@ -118,7 +118,7 @@ const getInviteToPayNotifyConfig = async ( ).title, fee: getFee(paymentRequest), projectType: - (await $admin.formatRawProjectTypes( + (await $public.formatRawProjectTypes( paymentRequest.sessionPreviewData?.["proposal.projectType"] as string[], )) || "Project type not submitted", serviceName: convertSlugToName(session.flow.slug), diff --git a/api.planx.uk/modules/auth/middleware.ts b/api.planx.uk/modules/auth/middleware.ts index 0548197f63..a751ea0a23 100644 --- a/api.planx.uk/modules/auth/middleware.ts +++ b/api.planx.uk/modules/auth/middleware.ts @@ -8,6 +8,9 @@ import passport from "passport"; import { RequestHandler } from "http-proxy-middleware"; import { Role } from "@opensystemslab/planx-core/types"; +import { AsyncLocalStorage } from "async_hooks"; + +export const userContext = new AsyncLocalStorage<{ user: Express.User }>(); /** * Validate that a provided string (e.g. API key) matches the expected value @@ -153,11 +156,22 @@ export const useRoleAuth: UseRoleAuth = }); } - next(); + // Establish a context for the current request/response call stack using AsyncLocalStorage + // The validated user will be accessible to all subsequent functions + // Store the raw JWT to pass on to plan-core client + userContext.run( + { + user: { + ...req.user, + jwt: req.cookies.jwt, + }, + }, + () => next(), + ); }); }; -// Convenience methods +// Convenience methods for role-based access export const useTeamViewerAuth = useRoleAuth([ "teamViewer", "teamEditor", @@ -165,3 +179,26 @@ export const useTeamViewerAuth = useRoleAuth([ ]); export const useTeamEditorAuth = useRoleAuth(["teamEditor", "platformAdmin"]); export const usePlatformAdminAuth = useRoleAuth(["platformAdmin"]); + +/** + * Allow any logged in user to access route, without checking roles + */ +export const useLoginAuth: RequestHandler = (req, res, next) => + useJWT(req, res, () => { + if (req?.user?.sub) { + userContext.run( + { + user: { + ...req.user, + jwt: req.cookies.jwt, + }, + }, + () => next(), + ); + } else { + return next({ + status: 401, + message: "No authorization token was found", + }); + } + }); diff --git a/api.planx.uk/modules/auth/service.ts b/api.planx.uk/modules/auth/service.ts index e6201b1170..db8dd538f1 100644 --- a/api.planx.uk/modules/auth/service.ts +++ b/api.planx.uk/modules/auth/service.ts @@ -8,6 +8,7 @@ export const buildJWT = async (email: string): Promise => { const data = { sub: user.id.toString(), + email, "https://hasura.io/jwt/claims": generateHasuraClaimsForUser(user), }; diff --git a/api.planx.uk/modules/misc/controller.ts b/api.planx.uk/modules/misc/controller.ts new file mode 100644 index 0000000000..7f283599ab --- /dev/null +++ b/api.planx.uk/modules/misc/controller.ts @@ -0,0 +1,35 @@ +import { RequestHandler } from "express"; +import { getClient } from "../../client"; +import { userContext } from "../auth/middleware"; +import { ServerError } from "../../errors"; + +export const getLoggedInUserDetails: RequestHandler = async ( + _req, + res, + next, +) => { + try { + const $client = getClient(); + + const email = userContext.getStore()?.user.email; + if (!email) + throw new ServerError({ + message: "User email missing from request", + status: 400, + }); + + const user = await $client.user.getByEmail(email); + if (!user) + throw new ServerError({ + message: `Unable to locate user with email ${email}`, + status: 400, + }); + + res.json(user); + } catch (error) { + next(error); + } +}; + +export const healthCheck: RequestHandler = (_req, res) => + res.json({ hello: "world" }); diff --git a/api.planx.uk/modules/misc/docs.yaml b/api.planx.uk/modules/misc/docs.yaml new file mode 100644 index 0000000000..3d28bd523d --- /dev/null +++ b/api.planx.uk/modules/misc/docs.yaml @@ -0,0 +1,81 @@ +openapi: 3.1.0 +info: + title: Planâś• API + version: 0.1.0 +tags: + - name: misc + description: Miscellaneous +paths: + /: + get: + summary: Health check + description: Confirms the API is healthy + tags: + - misc + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + hello: + type: string + example: + hello: world + /me: + get: + summary: Get information about currently logged in user + tags: + - misc + security: + - bearerAuth: [] + responses: + "200": + description: OK + content: + application/json: + schema: + type: object + properties: + id: + type: integer + format: int32 + example: 123 + firstName: + type: string + example: Albert + lastName: + type: string + example: Einstein + email: + type: string + example: albert@princeton.edu + isPlatformAdmin: + type: boolean + example: true + teams: + type: array + items: + type: object + properties: + team: + type: object + properties: + id: + type: integer + format: int32 + example: 123 + slug: + type: string + example: opensystemslab + name: + type: string + example: Open Systems Lab + role: + type: string + enum: ["teamEditor", "teamViewer"] + example: "teamEditor" + "401": + $ref: "#/components/responses/Unauthorised" diff --git a/api.planx.uk/modules/misc/routes.test.ts b/api.planx.uk/modules/misc/routes.test.ts new file mode 100644 index 0000000000..e80e97c015 --- /dev/null +++ b/api.planx.uk/modules/misc/routes.test.ts @@ -0,0 +1,111 @@ +import supertest from "supertest"; +import app from "../../server"; +import { authHeader, getJWT } from "../../tests/mockJWT"; +import { userContext } from "../auth/middleware"; + +const getStoreMock = jest.spyOn(userContext, "getStore"); + +const mockGetByEmail = jest.fn().mockResolvedValue({ + id: 36, + firstName: "Albert", + lastName: "Einstein", + email: "albert@princeton.edu", + isPlatformAdmin: true, + teams: [ + { + teamId: 1, + role: "teamEditor", + }, + { + teamId: 24, + role: "teamEditor", + }, + ], +}); + +jest.mock("@opensystemslab/planx-core", () => { + return { + CoreDomainClient: jest.fn().mockImplementation(() => ({ + user: { + getByEmail: () => mockGetByEmail(), + }, + })), + }; +}); + +describe("/me endpoint", () => { + beforeEach(() => { + getStoreMock.mockReturnValue({ + user: { + sub: "123", + email: "test@opensystemslab.io", + jwt: getJWT({ role: "teamEditor" }), + }, + }); + }); + + it("returns an error if authorization headers are not set", async () => { + await supertest(app) + .get("/me") + .expect(401) + .then((res) => { + expect(res.body).toEqual({ + error: "No authorization token was found", + }); + }); + }); + + it("returns an error for invalid user context", async () => { + getStoreMock.mockReturnValue({ + user: { + sub: "123", + email: undefined, + jwt: getJWT({ role: "teamEditor" }), + }, + }); + + await supertest(app) + .get("/me") + .set(authHeader({ role: "teamEditor" })) + .expect(400) + .then((res) => { + expect(res.body).toEqual({ + error: "User email missing from request", + }); + }); + }); + + it("returns an error for an invalid email address", async () => { + mockGetByEmail.mockResolvedValueOnce(null); + + await supertest(app) + .get("/me") + .set(authHeader({ role: "teamEditor" })) + .expect(400) + .then((res) => { + expect(res.body).toEqual({ + error: "Unable to locate user with email test@opensystemslab.io", + }); + }); + }); + + it("returns user details for a logged in user", async () => { + await supertest(app) + .get("/me") + .set(authHeader({ role: "teamEditor" })) + .expect(200) + .then((res) => { + expect(res.body).toHaveProperty("email", "albert@princeton.edu"); + expect(res.body.teams).toHaveLength(2); + }); + }); +}); + +describe("healthcheck endpoint", () => { + it("always returns a 200", async () => { + await supertest(app) + .get("/") + .expect(200) + .then((res) => expect(res.body).toHaveProperty("hello", "world")); + }); +}); diff --git a/api.planx.uk/modules/misc/routes.ts b/api.planx.uk/modules/misc/routes.ts new file mode 100644 index 0000000000..75d202e32e --- /dev/null +++ b/api.planx.uk/modules/misc/routes.ts @@ -0,0 +1,10 @@ +import { Router } from "express"; +import { useLoginAuth } from "../auth/middleware"; +import { getLoggedInUserDetails, healthCheck } from "./controller"; + +const router = Router(); + +router.get("/", healthCheck); +router.get("/me", useLoginAuth, getLoggedInUserDetails); + +export default router; diff --git a/api.planx.uk/modules/team/controller.ts b/api.planx.uk/modules/team/controller.ts index e6eabd9e8c..03d12aa738 100644 --- a/api.planx.uk/modules/team/controller.ts +++ b/api.planx.uk/modules/team/controller.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { $admin } from "../../client"; +import { getClient } from "../../client"; import { ValidatedRequestHandler } from "../../shared/middleware/validate"; interface TeamMemberResponse { @@ -39,7 +39,8 @@ export const addMember: UpsertMember = async (req, res) => { const { teamId } = req.params; const { userId, role } = req.body; - const isSuccess = await $admin.team.addMember({ teamId, userId, role }); + const $client = getClient(); + const isSuccess = await $client.team.addMember({ teamId, userId, role }); if (!isSuccess) return res.status(500).json({ message: "Failed to add member to team" }); @@ -51,7 +52,8 @@ export const changeMemberRole: UpsertMember = async (req, res) => { const { teamId } = req.params; const { userId, role } = req.body; - const isSuccess = await $admin.team.changeMemberRole({ + const $client = getClient(); + const isSuccess = await $client.team.changeMemberRole({ teamId, userId, role, @@ -67,7 +69,8 @@ export const removeMember: RemoveMember = async (req, res) => { const { teamId } = req.params; const { userId } = req.body; - const isSuccess = await $admin.team.removeMember({ teamId, userId }); + const $client = getClient(); + const isSuccess = await $client.team.removeMember({ teamId, userId }); if (!isSuccess) return res diff --git a/api.planx.uk/package.json b/api.planx.uk/package.json index eb3447520b..71cb212780 100644 --- a/api.planx.uk/package.json +++ b/api.planx.uk/package.json @@ -4,7 +4,7 @@ "private": true, "dependencies": { "@airbrake/node": "^2.1.8", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#17f3bf5", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#7e31b2e", "@types/isomorphic-fetch": "^0.0.36", "adm-zip": "^0.5.10", "aws-sdk": "^2.1441.0", diff --git a/api.planx.uk/pnpm-lock.yaml b/api.planx.uk/pnpm-lock.yaml index 1d70b98fd8..73d01ed96c 100644 --- a/api.planx.uk/pnpm-lock.yaml +++ b/api.planx.uk/pnpm-lock.yaml @@ -9,8 +9,8 @@ dependencies: specifier: ^2.1.8 version: 2.1.8 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#17f3bf5 - version: github.com/theopensystemslab/planx-core/17f3bf5 + specifier: git+https://github.com/theopensystemslab/planx-core#7e31b2e + version: github.com/theopensystemslab/planx-core/7e31b2e '@types/isomorphic-fetch': specifier: ^0.0.36 version: 0.0.36 @@ -753,8 +753,8 @@ packages: - supports-color dev: true - /@babel/runtime@7.22.11: - resolution: {integrity: sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==} + /@babel/runtime@7.22.15: + resolution: {integrity: sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.0 @@ -854,7 +854,7 @@ packages: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: '@babel/helper-module-imports': 7.22.5 - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.2 @@ -901,7 +901,7 @@ packages: react: optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 @@ -938,7 +938,7 @@ packages: react: optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 '@emotion/react': 11.11.1(react@18.2.0) @@ -1179,13 +1179,13 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.48.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.49.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.48.0 + eslint: 8.49.0 eslint-visitor-keys: 3.4.3 dev: false @@ -1219,8 +1219,8 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true - /@eslint/js@8.48.0: - resolution: {integrity: sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==} + /@eslint/js@8.49.0: + resolution: {integrity: sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false @@ -1274,6 +1274,18 @@ packages: minimatch: 3.1.2 transitivePeerDependencies: - supports-color + dev: true + + /@humanwhocodes/config-array@0.11.11: + resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: false /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} @@ -1621,8 +1633,8 @@ packages: resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} dev: false - /@mui/base@5.0.0-beta.13(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-uC0l97pBspfDAp+iz2cJq8YZ8Sd9i73V77+WzUiOAckIVEyCm5dyVDZCCO2/phmzckVEeZCGcytybkjMQuhPQw==} + /@mui/base@5.0.0-beta.16(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-OYxhC81c9bO0wobGcM8rrY5bRwpCXAI21BL0P2wz/2vTv4ek7ALz9+U5M8wgdmtRNUhmCmAB4L2WRwFRf5Cd8Q==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -1636,25 +1648,23 @@ packages: react-dom: optional: true dependencies: - '@babel/runtime': 7.22.11 - '@emotion/is-prop-valid': 1.2.1 + '@babel/runtime': 7.22.15 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) '@popperjs/core': 2.11.8 clsx: 2.0.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-is: 18.2.0 dev: false - /@mui/core-downloads-tracker@5.14.7: - resolution: {integrity: sha512-sCWTUNElBPgB30iLvWe3PU7SIlTKZNf6/E/sko85iHVeHCM6WPkDw+y89CrZYjhFNmPqt2fIQM/pZu+rP2lFLA==} + /@mui/core-downloads-tracker@5.14.10: + resolution: {integrity: sha512-kPHu/NhZq1k+vSZR5wq3AyUfD4bnfWAeuKpps0+8PS7ZHQ2Lyv1cXJh+PlFdCIOa0PK98rk3JPwMzS8BMhdHwQ==} dev: false - /@mui/material@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-jIZj9F7zMv6IlyaYDVv5M2Kp20jIX8c0kzuwteySHS/A0IvPVyomQEPtWc51MCbpDNCqzwoZUp3rQtA2lI8k7A==} + /@mui/material@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ejFMppnO+lzBXpzju+N4SSz0Mhmi5sihXUGcr5FxpgB6bfUP0Lpe32O0Sw/3s8xlmLEvG1fqVT0rRyAVMlCA+A==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -1674,14 +1684,14 @@ packages: react-dom: optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/base': 5.0.0-beta.13(react-dom@18.2.0)(react@18.2.0) - '@mui/core-downloads-tracker': 5.14.7 - '@mui/system': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/base': 5.0.0-beta.16(react-dom@18.2.0)(react@18.2.0) + '@mui/core-downloads-tracker': 5.14.10 + '@mui/system': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) '@types/react-transition-group': 4.4.6 clsx: 2.0.0 csstype: 3.1.2 @@ -1692,8 +1702,8 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false - /@mui/private-theming@5.14.7(react@18.2.0): - resolution: {integrity: sha512-Y86+hmDnJab2Ka42PgxKpK3oL7EiacbeeX3X/lG9LGO0wSc45wZjHeTfIlVSkkUCkexiMKEJp5NlSjZhr27NRQ==} + /@mui/private-theming@5.14.10(react@18.2.0): + resolution: {integrity: sha512-f67xOj3H06wWDT9xBg7hVL/HSKNF+HG1Kx0Pm23skkbEqD2Ef2Lif64e5nPdmWVv+7cISCYtSuE2aeuzrZe78w==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -1704,14 +1714,14 @@ packages: react: optional: true dependencies: - '@babel/runtime': 7.22.11 - '@mui/utils': 5.14.7(react@18.2.0) + '@babel/runtime': 7.22.15 + '@mui/utils': 5.14.10(react@18.2.0) prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/styled-engine@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-hKBETEDsIAkL8/mBwPiQj/vw28OeIhMXC3Tvj4J2bb9snxAKpiZioR1PwqP+6P41twsC/GKBd0Vr9oaWYaHuMg==} + /@mui/styled-engine@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-EJckxmQHrsBvDbFu1trJkvjNw/1R7jfNarnqPSnL+jEQawCkQIqVELWLrlOa611TFtxSJGkdUfCFXeJC203HVg==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.4.1 @@ -1725,7 +1735,7 @@ packages: react: optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/cache': 11.11.0 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) @@ -1734,8 +1744,8 @@ packages: react: 18.2.0 dev: false - /@mui/system@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-jeZtHglc+Pi6qjGoopT6O4RqYXVBMqHVOsjMGP0hxGSSPm1T4gsAu7jU8eqGx9YwwjvvJ0eotTjFqw7iJ6qE2Q==} + /@mui/system@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-QQmtTG/R4gjmLiL5ECQ7kRxLKDm8aKKD7seGZfbINtRVJDyFhKChA1a+K2bfqIAaBo1EMDv+6FWNT1Q5cRKjFA==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -1752,13 +1762,13 @@ packages: react: optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/private-theming': 5.14.7(react@18.2.0) - '@mui/styled-engine': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/private-theming': 5.14.10(react@18.2.0) + '@mui/styled-engine': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) clsx: 2.0.0 csstype: 3.1.2 prop-types: 15.8.1 @@ -1774,18 +1784,20 @@ packages: optional: true dev: false - /@mui/utils@5.14.7(react@18.2.0): - resolution: {integrity: sha512-RtheP/aBoPogVdi8vj8Vo2IFnRa4mZVmnD0RGlVZ49yF60rZs+xP4/KbpIrTr83xVs34QmHQ2aQ+IX7I0a0dDw==} + /@mui/utils@5.14.10(react@18.2.0): + resolution: {integrity: sha512-Rn+vYQX7FxkcW0riDX/clNUwKuOJFH45HiULxwmpgnzQoQr3A0lb+QYwaZ+FAkZrR7qLoHKmLQlcItu6LT0y/Q==} engines: {node: '>=12.0.0'} peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 react: ^17.0.0 || ^18.0.0 peerDependenciesMeta: + '@types/react': + optional: true react: optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@types/prop-types': 15.7.5 - '@types/react-is': 18.2.1 prop-types: 15.8.1 react: 18.2.0 react-is: 18.2.0 @@ -2125,12 +2137,6 @@ packages: /@types/range-parser@1.2.4: resolution: {integrity: sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==} - /@types/react-is@18.2.1: - resolution: {integrity: sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw==} - dependencies: - '@types/react': 18.2.14 - dev: false - /@types/react-transition-group@4.4.6: resolution: {integrity: sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==} dependencies: @@ -2682,7 +2688,7 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 cosmiconfig: 7.1.0 resolve: 1.22.2 dev: false @@ -3468,7 +3474,7 @@ packages: /dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 csstype: 3.1.2 dev: false @@ -3737,16 +3743,16 @@ packages: - supports-color dev: true - /eslint@8.48.0: - resolution: {integrity: sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==} + /eslint@8.49.0: + resolution: {integrity: sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.48.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.49.0) '@eslint-community/regexpp': 4.6.2 '@eslint/eslintrc': 2.1.2 - '@eslint/js': 8.48.0 - '@humanwhocodes/config-array': 0.11.10 + '@eslint/js': 8.49.0 + '@humanwhocodes/config-array': 0.11.11 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 @@ -5537,8 +5543,8 @@ packages: /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - /json-schema-to-typescript@13.0.2: - resolution: {integrity: sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==} + /json-schema-to-typescript@13.1.1: + resolution: {integrity: sha512-F3CYhtA7F3yPbb8vF7sFchk/2dnr1/yTKf8RcvoNpjnh67ZS/ZMH1ElLt5KHAtf2/bymiejLQQszszPWEeTdSw==} engines: {node: '>=12.0.0'} hasBin: true dependencies: @@ -6552,6 +6558,13 @@ packages: resolution: {integrity: sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==} engines: {node: '>=14'} hasBin: true + dev: true + + /prettier@3.0.3: + resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} + engines: {node: '>=14'} + hasBin: true + dev: false /pretty-format@23.6.0: resolution: {integrity: sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw==} @@ -6735,7 +6748,7 @@ packages: react-dom: optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -7346,6 +7359,10 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + /striptags@3.2.0: + resolution: {integrity: sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==} + dev: false + /strnum@1.0.5: resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} dev: false @@ -7827,6 +7844,12 @@ packages: /uuid@9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true + dev: true + + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -8050,8 +8073,8 @@ packages: resolution: {integrity: sha512-wvWkphh5WQsJbVk1tbx1l1Ly4yg+XecD+Mq280uBGt9wa5BKSWf4Mhp6GmrkPixhMxmabYY7RbzlwVP32pbGCg==} dev: false - github.com/theopensystemslab/planx-core/17f3bf5: - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/17f3bf5} + github.com/theopensystemslab/planx-core/7e31b2e: + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/7e31b2e} name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true @@ -8059,16 +8082,16 @@ packages: dependencies: '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/material': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0) '@types/geojson': 7946.0.10 ajv: 8.12.0 ajv-formats: 2.1.1(ajv@8.12.0) docx: 8.2.2 - eslint: 8.48.0 + eslint: 8.49.0 fast-xml-parser: 4.2.7 graphql: 16.8.0 graphql-request: 6.1.0(graphql@16.8.0) - json-schema-to-typescript: 13.0.2 + json-schema-to-typescript: 13.1.1 lodash.capitalize: 4.2.1 lodash.get: 4.4.2 lodash.groupby: 4.6.0 @@ -8080,11 +8103,12 @@ packages: lodash.property: 4.4.2 lodash.set: 4.3.2 lodash.startcase: 4.4.0 - prettier: 3.0.2 + prettier: 3.0.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + striptags: 3.2.0 type-fest: 4.3.1 - uuid: 9.0.0 + uuid: 9.0.1 zod: 3.22.2 transitivePeerDependencies: - '@types/react' diff --git a/api.planx.uk/saveAndReturn/resumeApplication.ts b/api.planx.uk/saveAndReturn/resumeApplication.ts index 1222e0efb2..292636fb79 100644 --- a/api.planx.uk/saveAndReturn/resumeApplication.ts +++ b/api.planx.uk/saveAndReturn/resumeApplication.ts @@ -5,7 +5,7 @@ import { LowCalSession, Team } from "../types"; import { convertSlugToName, getResumeLink, calculateExpiryDate } from "./utils"; import { sendEmail } from "../notify"; import type { SiteAddress } from "@opensystemslab/planx-core/types"; -import { $admin } from "../client"; +import { $public } from "../client"; /** * Send a "Resume" email to an applicant which list all open applications for a given council (team) @@ -121,7 +121,7 @@ const buildContentFromSessions = async ( const address: SiteAddress | undefined = session.data?.passport?.data?._address; const addressLine = address?.single_line_address || address?.title; - const projectType = await $admin.formatRawProjectTypes( + const projectType = await $public.formatRawProjectTypes( session.data?.passport?.data?.["proposal.projectType"], ); const resumeLink = getResumeLink(session, team, session.flow.slug); diff --git a/api.planx.uk/saveAndReturn/utils.ts b/api.planx.uk/saveAndReturn/utils.ts index b64e75af55..2de72f806f 100644 --- a/api.planx.uk/saveAndReturn/utils.ts +++ b/api.planx.uk/saveAndReturn/utils.ts @@ -4,7 +4,7 @@ import { gql } from "graphql-request"; import { adminGraphQLClient as adminClient } from "../hasura"; import { LowCalSession, Team } from "../types"; import { Template, getClientForTemplate, sendEmail } from "../notify"; -import { $admin } from "../client"; +import { $public } from "../client"; const DAYS_UNTIL_EXPIRY = 28; const REMINDER_DAYS_FROM_EXPIRY = [7, 1]; @@ -145,7 +145,7 @@ const getSessionDetails = async ( session.data.passport?.data?.["proposal.projectType"]; const projectTypes = passportProtectTypes && - (await $admin.formatRawProjectTypes(passportProtectTypes)); + (await $public.formatRawProjectTypes(passportProtectTypes)); const address: SiteAddress | undefined = session.data?.passport?.data?._address; const addressLine = address?.single_line_address || address?.title; diff --git a/api.planx.uk/server.test.js b/api.planx.uk/server.test.js index 125375c05e..7428f7baef 100644 --- a/api.planx.uk/server.test.js +++ b/api.planx.uk/server.test.js @@ -3,15 +3,6 @@ import supertest from "supertest"; import { queryMock } from "./tests/graphqlQueryMock"; import app from "./server"; -it("works", async () => { - await supertest(app) - .get("/") - .expect(200) - .then((response) => { - expect(response.body).toEqual({ hello: "world" }); - }); -}); - it("mocks hasura", async () => { queryMock.mockQuery({ name: "GetTeams", diff --git a/api.planx.uk/server.ts b/api.planx.uk/server.ts index 8b7b574e72..8b1a3bb5fb 100644 --- a/api.planx.uk/server.ts +++ b/api.planx.uk/server.ts @@ -79,6 +79,7 @@ import { getSessionSummary } from "./admin/session/summary"; import { googleStrategy } from "./modules/auth/strategy/google"; import authRoutes from "./modules/auth/routes"; import teamRoutes from "./modules/team/routes"; +import miscRoutes from "./modules/misc/routes"; import { useSwaggerDocs } from "./docs"; import { Role } from "@opensystemslab/planx-core/types"; @@ -192,6 +193,7 @@ app.use(passport.session()); app.use(urlencoded({ extended: true })); app.use(authRoutes); +app.use(miscRoutes); app.use("/team", teamRoutes); app.use("/gis", router); @@ -211,72 +213,6 @@ app.get("/hasura", async function (_req, res, next) { } }); -/** - * @swagger - * /me: - * get: - * summary: Get information about currently logged in user - * tags: - * - misc - * security: - * - userJWT: [] - * responses: - * '401': - * $ref: '#/components/responses/Unauthorised' - * '200': - * description: OK - * content: - * application/json: - * schema: - * type: object - * properties: - * id: - * type: integer - * format: int32 - * example: 123 - * first_name: - * type: string - * example: Albert - * last_name: - * type: string - * example: Einstein - * email: - * type: string - * example: albert@princeton.edu - * created_at: - * type: string - * example: 2020-08-11T11:28:38.237493+00:00 - * updated_at: - * type: string - * example: 2023-08-11T11:28:38.237493+00:00 - */ -app.get("/me", usePlatformAdminAuth, async function (req, res, next) { - try { - const user = await adminClient.request( - gql` - query ($id: Int!) { - users_by_pk(id: $id) { - id - first_name - last_name - email - created_at - updated_at - } - } - `, - { id: req.user?.sub }, - ); - - if (!user.users_by_pk) - next({ status: 404, message: `User (${req.user?.sub}) not found` }); - - res.json(user.users_by_pk); - } catch (err) { - next(err); - } -}); - app.get("/gis", (_req, _res, next) => { next({ status: 400, @@ -288,31 +224,6 @@ app.get("/gis/:localAuthority", locationSearch); app.get("/roads", classifiedRoadsSearch); -/** - * @swagger - * /: - * get: - * summary: Health check - * description: Confirms the API is healthy - * tags: - * - misc - * responses: - * '200': - * description: OK - * content: - * application/json: - * schema: - * type: object - * properties: - * hello: - * type: string - * example: - * hello: world - */ -app.get("/", (_req, res) => { - res.json({ hello: "world" }); -}); - app.use("/admin", usePlatformAdminAuth); app.get("/admin/feedback", downloadFeedbackCSV); app.get("/admin/session/:sessionId/xml", getOneAppXML); @@ -616,6 +527,7 @@ declare global { interface User { jwt: string; sub?: string; + email?: string; "https://hasura.io/jwt/claims"?: { "x-hasura-allowed-roles": Role[]; }; diff --git a/api.planx.uk/tests/mockJWT.ts b/api.planx.uk/tests/mockJWT.ts index 706c834b12..5e90671e6f 100644 --- a/api.planx.uk/tests/mockJWT.ts +++ b/api.planx.uk/tests/mockJWT.ts @@ -4,6 +4,7 @@ import { sign } from "jsonwebtoken"; function getJWT({ role }: { role: Role }) { const data = { sub: "123", + email: "test@opensystemslab.io", "https://hasura.io/jwt/claims": { "x-hasura-allowed-roles": [role], "x-hasura-default-role": role, diff --git a/e2e/tests/api-driven/pnpm-lock.yaml b/e2e/tests/api-driven/pnpm-lock.yaml index 199b1e8691..c0b30e9e7b 100644 --- a/e2e/tests/api-driven/pnpm-lock.yaml +++ b/e2e/tests/api-driven/pnpm-lock.yaml @@ -75,8 +75,8 @@ packages: js-tokens: 4.0.0 dev: false - /@babel/runtime@7.22.11: - resolution: {integrity: sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==} + /@babel/runtime@7.22.15: + resolution: {integrity: sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.0 @@ -259,7 +259,7 @@ packages: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: '@babel/helper-module-imports': 7.22.5 - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.2 @@ -304,7 +304,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 @@ -339,7 +339,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 '@emotion/react': 11.11.1(react@18.2.0) @@ -369,13 +369,13 @@ packages: resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} dev: false - /@eslint-community/eslint-utils@4.4.0(eslint@8.48.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.49.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.48.0 + eslint: 8.49.0 eslint-visitor-keys: 3.4.3 dev: false @@ -401,8 +401,8 @@ packages: - supports-color dev: false - /@eslint/js@8.48.0: - resolution: {integrity: sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==} + /@eslint/js@8.49.0: + resolution: {integrity: sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false @@ -442,8 +442,8 @@ packages: graphql: 16.8.0 dev: false - /@humanwhocodes/config-array@0.11.10: - resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==} + /@humanwhocodes/config-array@0.11.11: + resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 @@ -482,8 +482,8 @@ packages: resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} dev: false - /@mui/base@5.0.0-beta.13(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-uC0l97pBspfDAp+iz2cJq8YZ8Sd9i73V77+WzUiOAckIVEyCm5dyVDZCCO2/phmzckVEeZCGcytybkjMQuhPQw==} + /@mui/base@5.0.0-beta.16(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-OYxhC81c9bO0wobGcM8rrY5bRwpCXAI21BL0P2wz/2vTv4ek7ALz9+U5M8wgdmtRNUhmCmAB4L2WRwFRf5Cd8Q==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -493,25 +493,23 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 - '@emotion/is-prop-valid': 1.2.1 + '@babel/runtime': 7.22.15 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) '@popperjs/core': 2.11.8 clsx: 2.0.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-is: 18.2.0 dev: false - /@mui/core-downloads-tracker@5.14.7: - resolution: {integrity: sha512-sCWTUNElBPgB30iLvWe3PU7SIlTKZNf6/E/sko85iHVeHCM6WPkDw+y89CrZYjhFNmPqt2fIQM/pZu+rP2lFLA==} + /@mui/core-downloads-tracker@5.14.10: + resolution: {integrity: sha512-kPHu/NhZq1k+vSZR5wq3AyUfD4bnfWAeuKpps0+8PS7ZHQ2Lyv1cXJh+PlFdCIOa0PK98rk3JPwMzS8BMhdHwQ==} dev: false - /@mui/material@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-jIZj9F7zMv6IlyaYDVv5M2Kp20jIX8c0kzuwteySHS/A0IvPVyomQEPtWc51MCbpDNCqzwoZUp3rQtA2lI8k7A==} + /@mui/material@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ejFMppnO+lzBXpzju+N4SSz0Mhmi5sihXUGcr5FxpgB6bfUP0Lpe32O0Sw/3s8xlmLEvG1fqVT0rRyAVMlCA+A==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -527,14 +525,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/base': 5.0.0-beta.13(react-dom@18.2.0)(react@18.2.0) - '@mui/core-downloads-tracker': 5.14.7 - '@mui/system': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/base': 5.0.0-beta.16(react-dom@18.2.0)(react@18.2.0) + '@mui/core-downloads-tracker': 5.14.10 + '@mui/system': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) '@types/react-transition-group': 4.4.6 clsx: 2.0.0 csstype: 3.1.2 @@ -545,8 +543,8 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false - /@mui/private-theming@5.14.7(react@18.2.0): - resolution: {integrity: sha512-Y86+hmDnJab2Ka42PgxKpK3oL7EiacbeeX3X/lG9LGO0wSc45wZjHeTfIlVSkkUCkexiMKEJp5NlSjZhr27NRQ==} + /@mui/private-theming@5.14.10(react@18.2.0): + resolution: {integrity: sha512-f67xOj3H06wWDT9xBg7hVL/HSKNF+HG1Kx0Pm23skkbEqD2Ef2Lif64e5nPdmWVv+7cISCYtSuE2aeuzrZe78w==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -555,14 +553,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 - '@mui/utils': 5.14.7(react@18.2.0) + '@babel/runtime': 7.22.15 + '@mui/utils': 5.14.10(react@18.2.0) prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/styled-engine@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-hKBETEDsIAkL8/mBwPiQj/vw28OeIhMXC3Tvj4J2bb9snxAKpiZioR1PwqP+6P41twsC/GKBd0Vr9oaWYaHuMg==} + /@mui/styled-engine@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-EJckxmQHrsBvDbFu1trJkvjNw/1R7jfNarnqPSnL+jEQawCkQIqVELWLrlOa611TFtxSJGkdUfCFXeJC203HVg==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.4.1 @@ -574,7 +572,7 @@ packages: '@emotion/styled': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/cache': 11.11.0 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) @@ -583,8 +581,8 @@ packages: react: 18.2.0 dev: false - /@mui/system@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-jeZtHglc+Pi6qjGoopT6O4RqYXVBMqHVOsjMGP0hxGSSPm1T4gsAu7jU8eqGx9YwwjvvJ0eotTjFqw7iJ6qE2Q==} + /@mui/system@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-QQmtTG/R4gjmLiL5ECQ7kRxLKDm8aKKD7seGZfbINtRVJDyFhKChA1a+K2bfqIAaBo1EMDv+6FWNT1Q5cRKjFA==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -599,13 +597,13 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/private-theming': 5.14.7(react@18.2.0) - '@mui/styled-engine': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/private-theming': 5.14.10(react@18.2.0) + '@mui/styled-engine': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) clsx: 2.0.0 csstype: 3.1.2 prop-types: 15.8.1 @@ -621,15 +619,18 @@ packages: optional: true dev: false - /@mui/utils@5.14.7(react@18.2.0): - resolution: {integrity: sha512-RtheP/aBoPogVdi8vj8Vo2IFnRa4mZVmnD0RGlVZ49yF60rZs+xP4/KbpIrTr83xVs34QmHQ2aQ+IX7I0a0dDw==} + /@mui/utils@5.14.10(react@18.2.0): + resolution: {integrity: sha512-Rn+vYQX7FxkcW0riDX/clNUwKuOJFH45HiULxwmpgnzQoQr3A0lb+QYwaZ+FAkZrR7qLoHKmLQlcItu6LT0y/Q==} engines: {node: '>=12.0.0'} peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@types/prop-types': 15.7.5 - '@types/react-is': 18.2.1 prop-types: 15.8.1 react: 18.2.0 react-is: 18.2.0 @@ -723,12 +724,6 @@ packages: resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} dev: false - /@types/react-is@18.2.1: - resolution: {integrity: sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw==} - dependencies: - '@types/react': 18.2.18 - dev: false - /@types/react-transition-group@4.4.6: resolution: {integrity: sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==} dependencies: @@ -869,7 +864,7 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 cosmiconfig: 7.1.0 resolve: 1.22.2 dev: false @@ -1101,7 +1096,7 @@ packages: /dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 csstype: 3.1.2 dev: false @@ -1188,16 +1183,16 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false - /eslint@8.48.0: - resolution: {integrity: sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==} + /eslint@8.49.0: + resolution: {integrity: sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.48.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.49.0) '@eslint-community/regexpp': 4.6.2 '@eslint/eslintrc': 2.1.2 - '@eslint/js': 8.48.0 - '@humanwhocodes/config-array': 0.11.10 + '@eslint/js': 8.49.0 + '@humanwhocodes/config-array': 0.11.11 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 @@ -1588,8 +1583,8 @@ packages: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: false - /json-schema-to-typescript@13.0.2: - resolution: {integrity: sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==} + /json-schema-to-typescript@13.1.1: + resolution: {integrity: sha512-F3CYhtA7F3yPbb8vF7sFchk/2dnr1/yTKf8RcvoNpjnh67ZS/ZMH1ElLt5KHAtf2/bymiejLQQszszPWEeTdSw==} engines: {node: '>=12.0.0'} hasBin: true dependencies: @@ -1968,8 +1963,8 @@ packages: hasBin: true dev: false - /prettier@3.0.2: - resolution: {integrity: sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==} + /prettier@3.0.3: + resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} engines: {node: '>=14'} hasBin: true dev: false @@ -2037,7 +2032,7 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -2405,6 +2400,11 @@ packages: hasBin: true dev: false + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + /v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} dev: true @@ -2507,16 +2507,16 @@ packages: dependencies: '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/material': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0) '@types/geojson': 7946.0.10 ajv: 8.12.0 ajv-formats: 2.1.1(ajv@8.12.0) docx: 8.2.2 - eslint: 8.48.0 + eslint: 8.49.0 fast-xml-parser: 4.2.7 graphql: 16.8.0 graphql-request: 6.1.0(graphql@16.8.0) - json-schema-to-typescript: 13.0.2 + json-schema-to-typescript: 13.1.1 lodash.capitalize: 4.2.1 lodash.get: 4.4.2 lodash.groupby: 4.6.0 @@ -2528,11 +2528,11 @@ packages: lodash.property: 4.4.2 lodash.set: 4.3.2 lodash.startcase: 4.4.0 - prettier: 3.0.2 + prettier: 3.0.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) type-fest: 4.3.1 - uuid: 9.0.0 + uuid: 9.0.1 zod: 3.22.2 transitivePeerDependencies: - '@types/react' diff --git a/e2e/tests/ui-driven/pnpm-lock.yaml b/e2e/tests/ui-driven/pnpm-lock.yaml index 7a9edbc70f..07687e408f 100644 --- a/e2e/tests/ui-driven/pnpm-lock.yaml +++ b/e2e/tests/ui-driven/pnpm-lock.yaml @@ -87,8 +87,8 @@ packages: js-tokens: 4.0.0 dev: false - /@babel/runtime@7.22.10: - resolution: {integrity: sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==} + /@babel/runtime@7.22.15: + resolution: {integrity: sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.0 @@ -117,7 +117,7 @@ packages: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: '@babel/helper-module-imports': 7.22.5 - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.2 @@ -162,7 +162,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 '@emotion/babel-plugin': 11.11.0 '@emotion/cache': 11.11.0 '@emotion/serialize': 1.1.2 @@ -197,7 +197,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 '@emotion/react': 11.11.1(react@18.2.0) @@ -236,13 +236,13 @@ packages: eslint: 8.47.0 eslint-visitor-keys: 3.4.3 - /@eslint-community/eslint-utils@4.4.0(eslint@8.48.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.49.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.48.0 + eslint: 8.49.0 eslint-visitor-keys: 3.4.3 dev: false @@ -270,8 +270,8 @@ packages: resolution: {integrity: sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@eslint/js@8.48.0: - resolution: {integrity: sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==} + /@eslint/js@8.49.0: + resolution: {integrity: sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false @@ -321,6 +321,17 @@ packages: transitivePeerDependencies: - supports-color + /@humanwhocodes/config-array@0.11.11: + resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: false + /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -332,8 +343,8 @@ packages: resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} dev: false - /@mui/base@5.0.0-beta.13(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-uC0l97pBspfDAp+iz2cJq8YZ8Sd9i73V77+WzUiOAckIVEyCm5dyVDZCCO2/phmzckVEeZCGcytybkjMQuhPQw==} + /@mui/base@5.0.0-beta.16(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-OYxhC81c9bO0wobGcM8rrY5bRwpCXAI21BL0P2wz/2vTv4ek7ALz9+U5M8wgdmtRNUhmCmAB4L2WRwFRf5Cd8Q==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -343,25 +354,23 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.10 - '@emotion/is-prop-valid': 1.2.1 + '@babel/runtime': 7.22.15 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) '@popperjs/core': 2.11.8 clsx: 2.0.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-is: 18.2.0 dev: false - /@mui/core-downloads-tracker@5.14.7: - resolution: {integrity: sha512-sCWTUNElBPgB30iLvWe3PU7SIlTKZNf6/E/sko85iHVeHCM6WPkDw+y89CrZYjhFNmPqt2fIQM/pZu+rP2lFLA==} + /@mui/core-downloads-tracker@5.14.10: + resolution: {integrity: sha512-kPHu/NhZq1k+vSZR5wq3AyUfD4bnfWAeuKpps0+8PS7ZHQ2Lyv1cXJh+PlFdCIOa0PK98rk3JPwMzS8BMhdHwQ==} dev: false - /@mui/material@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-jIZj9F7zMv6IlyaYDVv5M2Kp20jIX8c0kzuwteySHS/A0IvPVyomQEPtWc51MCbpDNCqzwoZUp3rQtA2lI8k7A==} + /@mui/material@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ejFMppnO+lzBXpzju+N4SSz0Mhmi5sihXUGcr5FxpgB6bfUP0Lpe32O0Sw/3s8xlmLEvG1fqVT0rRyAVMlCA+A==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -377,14 +386,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/base': 5.0.0-beta.13(react-dom@18.2.0)(react@18.2.0) - '@mui/core-downloads-tracker': 5.14.7 - '@mui/system': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/base': 5.0.0-beta.16(react-dom@18.2.0)(react@18.2.0) + '@mui/core-downloads-tracker': 5.14.10 + '@mui/system': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) '@types/react-transition-group': 4.4.6 clsx: 2.0.0 csstype: 3.1.2 @@ -395,8 +404,8 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false - /@mui/private-theming@5.14.7(react@18.2.0): - resolution: {integrity: sha512-Y86+hmDnJab2Ka42PgxKpK3oL7EiacbeeX3X/lG9LGO0wSc45wZjHeTfIlVSkkUCkexiMKEJp5NlSjZhr27NRQ==} + /@mui/private-theming@5.14.10(react@18.2.0): + resolution: {integrity: sha512-f67xOj3H06wWDT9xBg7hVL/HSKNF+HG1Kx0Pm23skkbEqD2Ef2Lif64e5nPdmWVv+7cISCYtSuE2aeuzrZe78w==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -405,14 +414,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.10 - '@mui/utils': 5.14.7(react@18.2.0) + '@babel/runtime': 7.22.15 + '@mui/utils': 5.14.10(react@18.2.0) prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/styled-engine@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-hKBETEDsIAkL8/mBwPiQj/vw28OeIhMXC3Tvj4J2bb9snxAKpiZioR1PwqP+6P41twsC/GKBd0Vr9oaWYaHuMg==} + /@mui/styled-engine@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-EJckxmQHrsBvDbFu1trJkvjNw/1R7jfNarnqPSnL+jEQawCkQIqVELWLrlOa611TFtxSJGkdUfCFXeJC203HVg==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.4.1 @@ -424,7 +433,7 @@ packages: '@emotion/styled': optional: true dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 '@emotion/cache': 11.11.0 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) @@ -433,8 +442,8 @@ packages: react: 18.2.0 dev: false - /@mui/system@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): - resolution: {integrity: sha512-jeZtHglc+Pi6qjGoopT6O4RqYXVBMqHVOsjMGP0hxGSSPm1T4gsAu7jU8eqGx9YwwjvvJ0eotTjFqw7iJ6qE2Q==} + /@mui/system@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-QQmtTG/R4gjmLiL5ECQ7kRxLKDm8aKKD7seGZfbINtRVJDyFhKChA1a+K2bfqIAaBo1EMDv+6FWNT1Q5cRKjFA==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -449,13 +458,13 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/private-theming': 5.14.7(react@18.2.0) - '@mui/styled-engine': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/private-theming': 5.14.10(react@18.2.0) + '@mui/styled-engine': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) '@mui/types': 7.2.4 - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(react@18.2.0) clsx: 2.0.0 csstype: 3.1.2 prop-types: 15.8.1 @@ -471,15 +480,18 @@ packages: optional: true dev: false - /@mui/utils@5.14.7(react@18.2.0): - resolution: {integrity: sha512-RtheP/aBoPogVdi8vj8Vo2IFnRa4mZVmnD0RGlVZ49yF60rZs+xP4/KbpIrTr83xVs34QmHQ2aQ+IX7I0a0dDw==} + /@mui/utils@5.14.10(react@18.2.0): + resolution: {integrity: sha512-Rn+vYQX7FxkcW0riDX/clNUwKuOJFH45HiULxwmpgnzQoQr3A0lb+QYwaZ+FAkZrR7qLoHKmLQlcItu6LT0y/Q==} engines: {node: '>=12.0.0'} peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 '@types/prop-types': 15.7.5 - '@types/react-is': 18.2.1 prop-types: 15.8.1 react: 18.2.0 react-is: 18.2.0 @@ -560,12 +572,6 @@ packages: resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} dev: false - /@types/react-is@18.2.1: - resolution: {integrity: sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw==} - dependencies: - '@types/react': 18.2.20 - dev: false - /@types/react-transition-group@4.4.6: resolution: {integrity: sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==} dependencies: @@ -711,7 +717,7 @@ packages: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 cosmiconfig: 7.1.0 resolve: 1.22.4 dev: false @@ -976,7 +982,7 @@ packages: /dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 csstype: 3.1.2 dev: false @@ -1120,16 +1126,16 @@ packages: transitivePeerDependencies: - supports-color - /eslint@8.48.0: - resolution: {integrity: sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==} + /eslint@8.49.0: + resolution: {integrity: sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.48.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.49.0) '@eslint-community/regexpp': 4.6.2 '@eslint/eslintrc': 2.1.2 - '@eslint/js': 8.48.0 - '@humanwhocodes/config-array': 0.11.10 + '@eslint/js': 8.49.0 + '@humanwhocodes/config-array': 0.11.11 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 @@ -1517,8 +1523,8 @@ packages: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: false - /json-schema-to-typescript@13.0.2: - resolution: {integrity: sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==} + /json-schema-to-typescript@13.1.1: + resolution: {integrity: sha512-F3CYhtA7F3yPbb8vF7sFchk/2dnr1/yTKf8RcvoNpjnh67ZS/ZMH1ElLt5KHAtf2/bymiejLQQszszPWEeTdSw==} engines: {node: '>=12.0.0'} hasBin: true dependencies: @@ -1903,8 +1909,8 @@ packages: hasBin: true dev: false - /prettier@3.0.2: - resolution: {integrity: sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==} + /prettier@3.0.3: + resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} engines: {node: '>=14'} hasBin: true dev: false @@ -1975,7 +1981,7 @@ packages: react: '>=16.6.0' react-dom: '>=16.6.0' dependencies: - '@babel/runtime': 7.22.10 + '@babel/runtime': 7.22.15 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -2293,6 +2299,11 @@ packages: hasBin: true dev: false + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + /vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -2376,16 +2387,16 @@ packages: dependencies: '@emotion/react': 11.11.1(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(react@18.2.0) - '@mui/material': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react-dom@18.2.0)(react@18.2.0) '@types/geojson': 7946.0.10 ajv: 8.12.0 ajv-formats: 2.1.1(ajv@8.12.0) docx: 8.2.2 - eslint: 8.48.0 + eslint: 8.49.0 fast-xml-parser: 4.2.7 graphql: 16.8.0 graphql-request: 6.1.0(graphql@16.8.0) - json-schema-to-typescript: 13.0.2 + json-schema-to-typescript: 13.1.1 lodash.capitalize: 4.2.1 lodash.get: 4.4.2 lodash.groupby: 4.6.0 @@ -2397,11 +2408,11 @@ packages: lodash.property: 4.4.2 lodash.set: 4.3.2 lodash.startcase: 4.4.0 - prettier: 3.0.2 + prettier: 3.0.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) type-fest: 4.3.1 - uuid: 9.0.0 + uuid: 9.0.1 zod: 3.22.2 transitivePeerDependencies: - '@types/react' diff --git a/editor.planx.uk/package.json b/editor.planx.uk/package.json index 8f82ea9b81..3fad9944b0 100644 --- a/editor.planx.uk/package.json +++ b/editor.planx.uk/package.json @@ -14,7 +14,7 @@ "@mui/styles": "^5.14.5", "@mui/utils": "^5.14.5", "@opensystemslab/map": "^0.7.5", - "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#4e3d09f", + "@opensystemslab/planx-core": "git+https://github.com/theopensystemslab/planx-core#7e31b2e", "@tiptap/core": "^2.0.3", "@tiptap/extension-bold": "^2.0.3", "@tiptap/extension-bubble-menu": "^2.1.6", diff --git a/editor.planx.uk/pnpm-lock.yaml b/editor.planx.uk/pnpm-lock.yaml index 1bbee1fe10..dedae47e26 100644 --- a/editor.planx.uk/pnpm-lock.yaml +++ b/editor.planx.uk/pnpm-lock.yaml @@ -46,8 +46,8 @@ dependencies: specifier: ^0.7.5 version: 0.7.5 '@opensystemslab/planx-core': - specifier: git+https://github.com/theopensystemslab/planx-core#4e3d09f - version: github.com/theopensystemslab/planx-core/4e3d09f(@types/react@18.2.20) + specifier: git+https://github.com/theopensystemslab/planx-core#7e31b2e + version: github.com/theopensystemslab/planx-core/7e31b2e(@types/react@18.2.20) '@tiptap/core': specifier: ^2.0.3 version: 2.0.3(@tiptap/pm@2.0.3) @@ -3194,6 +3194,12 @@ packages: dependencies: regenerator-runtime: 0.14.0 + /@babel/runtime@7.22.15: + resolution: {integrity: sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.0 + /@babel/runtime@7.22.6: resolution: {integrity: sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==} engines: {node: '>=6.9.0'} @@ -4311,13 +4317,13 @@ packages: eslint: 8.44.0 eslint-visitor-keys: 3.4.3 - /@eslint-community/eslint-utils@4.4.0(eslint@8.48.0): + /@eslint-community/eslint-utils@4.4.0(eslint@8.49.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.48.0 + eslint: 8.49.0 eslint-visitor-keys: 3.4.3 dev: false @@ -4367,8 +4373,8 @@ packages: resolution: {integrity: sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - /@eslint/js@8.48.0: - resolution: {integrity: sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==} + /@eslint/js@8.49.0: + resolution: {integrity: sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false @@ -4458,6 +4464,17 @@ packages: transitivePeerDependencies: - supports-color + /@humanwhocodes/config-array@0.11.11: + resolution: {integrity: sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 1.2.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: false + /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -4961,7 +4978,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@material-ui/styles': 4.11.5(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) '@material-ui/system': 4.12.2(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) '@material-ui/types': 5.1.0(@types/react@18.2.20) @@ -4990,7 +5007,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/hash': 0.8.0 '@material-ui/types': 5.1.0(@types/react@18.2.20) '@material-ui/utils': 4.11.3(react-dom@18.2.0)(react@18.2.0) @@ -5022,7 +5039,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@material-ui/utils': 4.11.3(react-dom@18.2.0)(react@18.2.0) '@types/react': 18.2.20 csstype: 2.6.21 @@ -5049,7 +5066,7 @@ packages: react: ^16.8.0 || ^17.0.0 react-dom: ^16.8.0 || ^17.0.0 dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -5090,8 +5107,8 @@ packages: react-is: 18.2.0 dev: false - /@mui/base@5.0.0-beta.13(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-uC0l97pBspfDAp+iz2cJq8YZ8Sd9i73V77+WzUiOAckIVEyCm5dyVDZCCO2/phmzckVEeZCGcytybkjMQuhPQw==} + /@mui/base@5.0.0-beta.16(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-OYxhC81c9bO0wobGcM8rrY5bRwpCXAI21BL0P2wz/2vTv4ek7ALz9+U5M8wgdmtRNUhmCmAB4L2WRwFRf5Cd8Q==} engines: {node: '>=12.0.0'} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -5101,26 +5118,24 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 - '@emotion/is-prop-valid': 1.2.1 + '@babel/runtime': 7.22.15 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) '@mui/types': 7.2.4(@types/react@18.2.20) - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(@types/react@18.2.20)(react@18.2.0) '@popperjs/core': 2.11.8 '@types/react': 18.2.20 clsx: 2.0.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-is: 18.2.0 dev: false - /@mui/core-downloads-tracker@5.14.5: - resolution: {integrity: sha512-+wpGH1USwPcKMFPMvXqYPC6fEvhxM3FzxC8lyDiNK/imLyyJ6y2DPb1Oue7OGIKJWBmYBqrWWtfovrxd1aJHTA==} + /@mui/core-downloads-tracker@5.14.10: + resolution: {integrity: sha512-kPHu/NhZq1k+vSZR5wq3AyUfD4bnfWAeuKpps0+8PS7ZHQ2Lyv1cXJh+PlFdCIOa0PK98rk3JPwMzS8BMhdHwQ==} dev: false - /@mui/core-downloads-tracker@5.14.7: - resolution: {integrity: sha512-sCWTUNElBPgB30iLvWe3PU7SIlTKZNf6/E/sko85iHVeHCM6WPkDw+y89CrZYjhFNmPqt2fIQM/pZu+rP2lFLA==} + /@mui/core-downloads-tracker@5.14.5: + resolution: {integrity: sha512-+wpGH1USwPcKMFPMvXqYPC6fEvhxM3FzxC8lyDiNK/imLyyJ6y2DPb1Oue7OGIKJWBmYBqrWWtfovrxd1aJHTA==} dev: false /@mui/icons-material@5.14.3(@mui/material@5.14.5)(@types/react@18.2.20)(react@18.2.0): @@ -5140,8 +5155,8 @@ packages: react: 18.2.0 dev: false - /@mui/material@5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-4qa4GMfuZH0Ai3mttk5ccXP8a3sf7aPlAJwyMrUSz6h9hPri6BPou94zeu3rENhhmKLby9S/W1y+pmficy8JKA==} + /@mui/material@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ejFMppnO+lzBXpzju+N4SSz0Mhmi5sihXUGcr5FxpgB6bfUP0Lpe32O0Sw/3s8xlmLEvG1fqVT0rRyAVMlCA+A==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -5157,14 +5172,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.6 + '@babel/runtime': 7.22.15 '@emotion/react': 11.11.1(@types/react@18.2.20)(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.20)(react@18.2.0) - '@mui/base': 5.0.0-beta.11(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) - '@mui/core-downloads-tracker': 5.14.5 - '@mui/system': 5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react@18.2.0) + '@mui/base': 5.0.0-beta.16(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) + '@mui/core-downloads-tracker': 5.14.10 + '@mui/system': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react@18.2.0) '@mui/types': 7.2.4(@types/react@18.2.20) - '@mui/utils': 5.14.5(react@18.2.0) + '@mui/utils': 5.14.10(@types/react@18.2.20)(react@18.2.0) '@types/react': 18.2.20 '@types/react-transition-group': 4.4.6 clsx: 2.0.0 @@ -5176,8 +5191,8 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false - /@mui/material@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-jIZj9F7zMv6IlyaYDVv5M2Kp20jIX8c0kzuwteySHS/A0IvPVyomQEPtWc51MCbpDNCqzwoZUp3rQtA2lI8k7A==} + /@mui/material@5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-4qa4GMfuZH0Ai3mttk5ccXP8a3sf7aPlAJwyMrUSz6h9hPri6BPou94zeu3rENhhmKLby9S/W1y+pmficy8JKA==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -5193,14 +5208,14 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.6 '@emotion/react': 11.11.1(@types/react@18.2.20)(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.20)(react@18.2.0) - '@mui/base': 5.0.0-beta.13(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) - '@mui/core-downloads-tracker': 5.14.7 - '@mui/system': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react@18.2.0) + '@mui/base': 5.0.0-beta.11(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) + '@mui/core-downloads-tracker': 5.14.5 + '@mui/system': 5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react@18.2.0) '@mui/types': 7.2.4(@types/react@18.2.20) - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.5(react@18.2.0) '@types/react': 18.2.20 '@types/react-transition-group': 4.4.6 clsx: 2.0.0 @@ -5212,6 +5227,23 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false + /@mui/private-theming@5.14.10(@types/react@18.2.20)(react@18.2.0): + resolution: {integrity: sha512-f67xOj3H06wWDT9xBg7hVL/HSKNF+HG1Kx0Pm23skkbEqD2Ef2Lif64e5nPdmWVv+7cISCYtSuE2aeuzrZe78w==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.15 + '@mui/utils': 5.14.10(@types/react@18.2.20)(react@18.2.0) + '@types/react': 18.2.20 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + /@mui/private-theming@5.14.5(@types/react@18.2.20)(react@18.2.0): resolution: {integrity: sha512-cC4C5RrpXpDaaZyH9QwmPhRLgz+f2SYbOty3cPkk4qPSOSfif2ZEcDD9HTENKDDd9deB+xkPKzzZhi8cxIx8Ig==} engines: {node: '>=12.0.0'} @@ -5246,6 +5278,28 @@ packages: react: 18.2.0 dev: false + /@mui/styled-engine@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): + resolution: {integrity: sha512-EJckxmQHrsBvDbFu1trJkvjNw/1R7jfNarnqPSnL+jEQawCkQIqVELWLrlOa611TFtxSJGkdUfCFXeJC203HVg==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + dependencies: + '@babel/runtime': 7.22.15 + '@emotion/cache': 11.11.0 + '@emotion/react': 11.11.1(@types/react@18.2.20)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.20)(react@18.2.0) + csstype: 3.1.2 + prop-types: 15.8.1 + react: 18.2.0 + dev: false + /@mui/styled-engine@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0): resolution: {integrity: sha512-hKBETEDsIAkL8/mBwPiQj/vw28OeIhMXC3Tvj4J2bb9snxAKpiZioR1PwqP+6P41twsC/GKBd0Vr9oaWYaHuMg==} engines: {node: '>=12.0.0'} @@ -5299,8 +5353,8 @@ packages: react: 18.2.0 dev: false - /@mui/system@5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react@18.2.0): - resolution: {integrity: sha512-mextXZHDeGcR7E1kx43TRARrVXy+gI4wzpUgNv7MqZs1dvTVXQGVeAT6ydj9d6FUqHBPMNLGV/21vJOrpqsL+w==} + /@mui/system@5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react@18.2.0): + resolution: {integrity: sha512-QQmtTG/R4gjmLiL5ECQ7kRxLKDm8aKKD7seGZfbINtRVJDyFhKChA1a+K2bfqIAaBo1EMDv+6FWNT1Q5cRKjFA==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -5315,13 +5369,13 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.22.15 '@emotion/react': 11.11.1(@types/react@18.2.20)(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.20)(react@18.2.0) - '@mui/private-theming': 5.14.7(@types/react@18.2.20)(react@18.2.0) - '@mui/styled-engine': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) + '@mui/private-theming': 5.14.10(@types/react@18.2.20)(react@18.2.0) + '@mui/styled-engine': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(react@18.2.0) '@mui/types': 7.2.4(@types/react@18.2.20) - '@mui/utils': 5.14.7(react@18.2.0) + '@mui/utils': 5.14.10(@types/react@18.2.20)(react@18.2.0) '@types/react': 18.2.20 clsx: 2.0.0 csstype: 3.1.2 @@ -5329,8 +5383,8 @@ packages: react: 18.2.0 dev: false - /@mui/system@5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react@18.2.0): - resolution: {integrity: sha512-jeZtHglc+Pi6qjGoopT6O4RqYXVBMqHVOsjMGP0hxGSSPm1T4gsAu7jU8eqGx9YwwjvvJ0eotTjFqw7iJ6qE2Q==} + /@mui/system@5.14.5(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react@18.2.0): + resolution: {integrity: sha512-mextXZHDeGcR7E1kx43TRARrVXy+gI4wzpUgNv7MqZs1dvTVXQGVeAT6ydj9d6FUqHBPMNLGV/21vJOrpqsL+w==} engines: {node: '>=12.0.0'} peerDependencies: '@emotion/react': ^11.5.0 @@ -5370,6 +5424,24 @@ packages: '@types/react': 18.2.20 dev: false + /@mui/utils@5.14.10(@types/react@18.2.20)(react@18.2.0): + resolution: {integrity: sha512-Rn+vYQX7FxkcW0riDX/clNUwKuOJFH45HiULxwmpgnzQoQr3A0lb+QYwaZ+FAkZrR7qLoHKmLQlcItu6LT0y/Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.15 + '@types/prop-types': 15.7.5 + '@types/react': 18.2.20 + prop-types: 15.8.1 + react: 18.2.0 + react-is: 18.2.0 + dev: false + /@mui/utils@5.14.5(react@18.2.0): resolution: {integrity: sha512-6Hzw63VR9C5xYv+CbjndoRLU6Gntal8rJ5W+GUzkyHrGWIyYPWZPa6AevnyGioySNETATe1H9oXS8f/7qgIHJA==} engines: {node: '>=12.0.0'} @@ -11597,16 +11669,16 @@ packages: transitivePeerDependencies: - supports-color - /eslint@8.48.0: - resolution: {integrity: sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==} + /eslint@8.49.0: + resolution: {integrity: sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.48.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.49.0) '@eslint-community/regexpp': 4.6.2 '@eslint/eslintrc': 2.1.2 - '@eslint/js': 8.48.0 - '@humanwhocodes/config-array': 0.11.10 + '@eslint/js': 8.49.0 + '@humanwhocodes/config-array': 0.11.11 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 @@ -14283,8 +14355,8 @@ packages: /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - /json-schema-to-typescript@13.0.2: - resolution: {integrity: sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==} + /json-schema-to-typescript@13.1.1: + resolution: {integrity: sha512-F3CYhtA7F3yPbb8vF7sFchk/2dnr1/yTKf8RcvoNpjnh67ZS/ZMH1ElLt5KHAtf2/bymiejLQQszszPWEeTdSw==} engines: {node: '>=12.0.0'} hasBin: true dependencies: @@ -16750,8 +16822,8 @@ packages: hasBin: true dev: true - /prettier@3.0.2: - resolution: {integrity: sha512-o2YR9qtniXvwEZlOKbveKfDQVyqxbEIWn48Z8m3ZJjBjcCmUy3xZGIv+7AkaeuaTr6yPXJjwv07ZWlsWbEy1rQ==} + /prettier@3.0.3: + resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==} engines: {node: '>=14'} hasBin: true dev: false @@ -19943,6 +20015,11 @@ packages: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + /uvu@0.5.6: resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} engines: {node: '>=8'} @@ -20697,9 +20774,9 @@ packages: use-sync-external-store: 1.2.0(react@18.2.0) dev: false - github.com/theopensystemslab/planx-core/4e3d09f(@types/react@18.2.20): - resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/4e3d09f} - id: github.com/theopensystemslab/planx-core/4e3d09f + github.com/theopensystemslab/planx-core/7e31b2e(@types/react@18.2.20): + resolution: {tarball: https://codeload.github.com/theopensystemslab/planx-core/tar.gz/7e31b2e} + id: github.com/theopensystemslab/planx-core/7e31b2e name: '@opensystemslab/planx-core' version: 1.0.0 prepare: true @@ -20707,16 +20784,16 @@ packages: dependencies: '@emotion/react': 11.11.1(@types/react@18.2.20)(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.20)(react@18.2.0) - '@mui/material': 5.14.7(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 5.14.10(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.20)(react-dom@18.2.0)(react@18.2.0) '@types/geojson': 7946.0.10 ajv: 8.12.0 ajv-formats: 2.1.1(ajv@8.12.0) docx: 8.2.2 - eslint: 8.48.0 + eslint: 8.49.0 fast-xml-parser: 4.2.7 graphql: 16.8.0 graphql-request: 6.1.0(graphql@16.8.0) - json-schema-to-typescript: 13.0.2 + json-schema-to-typescript: 13.1.1 lodash.capitalize: 4.2.1 lodash.get: 4.4.2 lodash.groupby: 4.6.0 @@ -20728,11 +20805,12 @@ packages: lodash.property: 4.4.2 lodash.set: 4.3.2 lodash.startcase: 4.4.0 - prettier: 3.0.2 + prettier: 3.0.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + striptags: 3.2.0 type-fest: 4.3.1 - uuid: 9.0.0 + uuid: 9.0.1 zod: 3.22.2 transitivePeerDependencies: - '@types/react'