From ec460a5db4b8883c08cdcbcd7e559453d0efbf33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Tue, 23 Jun 2026 12:00:38 -0400 Subject: [PATCH 1/9] feat: add version information to retrieveNewSubmissions API response --- src/lib/vault/getNewFormSubmissions.ts | 8 ++++++-- src/lib/vault/mappers/formSubmission.mapper.ts | 6 +++++- src/lib/vault/types/formSubmission.types.ts | 1 + src/operations/retrieveNewSubmissions.v1.ts | 7 ++++++- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/lib/vault/getNewFormSubmissions.ts b/src/lib/vault/getNewFormSubmissions.ts index 553f178d..3525e1f8 100644 --- a/src/lib/vault/getNewFormSubmissions.ts +++ b/src/lib/vault/getNewFormSubmissions.ts @@ -1,4 +1,5 @@ import { QueryCommand, type QueryCommandOutput } from "@aws-sdk/lib-dynamodb"; +import { ENVIRONMENT_MODE, EnvironmentMode } from "@config"; import { AwsServicesConnector } from "@lib/integration/awsServicesConnector.js"; import { logMessage } from "@lib/logging/logger.js"; import { mapNewFormSubmissionFromDynamoDbResponse } from "@lib/vault/mappers/formSubmission.mapper.js"; @@ -17,12 +18,15 @@ export async function getNewFormSubmissions( await AwsServicesConnector.getInstance().dynamodbClient.send( new QueryCommand({ TableName: "Vault", - IndexName: "StatusCreatedAt", + IndexName: + ENVIRONMENT_MODE !== EnvironmentMode.production // Condition to be deleted once StatusCreatedAt_v2 becomes available in Production + ? "StatusCreatedAt_v2" + : "StatusCreatedAt", ExclusiveStartKey: lastEvaluatedKey ?? undefined, Limit: limit - newFormSubmissions.length, KeyConditionExpression: "FormID = :formId AND begins_with(#statusCreatedAt, :status)", - ProjectionExpression: "#name,CreatedAt", + ProjectionExpression: `#name,CreatedAt${ENVIRONMENT_MODE !== EnvironmentMode.production ? ",Version" : ""}`, // Condition to be deleted once StatusCreatedAt_v2 becomes available in Production ExpressionAttributeNames: { "#statusCreatedAt": "Status#CreatedAt", "#name": "Name", diff --git a/src/lib/vault/mappers/formSubmission.mapper.ts b/src/lib/vault/mappers/formSubmission.mapper.ts index 3f66991c..de540535 100644 --- a/src/lib/vault/mappers/formSubmission.mapper.ts +++ b/src/lib/vault/mappers/formSubmission.mapper.ts @@ -11,13 +11,16 @@ export function mapNewFormSubmissionFromDynamoDbResponse( response: Record, ): NewFormSubmission { try { + // response.Version could be undefined if API users are retrieving responses that have been created before we implemented the form versioning feature if (response.Name === undefined || response.CreatedAt === undefined) { throw new Error("Missing key properties in DynamoDB response"); } if ( typeof response.Name !== "string" || - typeof response.CreatedAt !== "number" + typeof response.CreatedAt !== "number" || + // response.Version could be undefined if API users are retrieving responses that have been created before we implemented the form versioning feature + (response.Version !== undefined && typeof response.Version !== "number") ) { throw new Error("Unexpected type in DynamoDB response"); } @@ -25,6 +28,7 @@ export function mapNewFormSubmissionFromDynamoDbResponse( return { name: response.Name, createdAt: response.CreatedAt, + version: response.Version ?? 1, }; } catch (error) { logMessage.info( diff --git a/src/lib/vault/types/formSubmission.types.ts b/src/lib/vault/types/formSubmission.types.ts index a4e56a3a..ff3f078a 100644 --- a/src/lib/vault/types/formSubmission.types.ts +++ b/src/lib/vault/types/formSubmission.types.ts @@ -1,6 +1,7 @@ export type NewFormSubmission = { name: string; createdAt: number; + version: number; }; export const SubmissionStatus = { diff --git a/src/operations/retrieveNewSubmissions.v1.ts b/src/operations/retrieveNewSubmissions.v1.ts index d5a2d158..f5f3a5e2 100644 --- a/src/operations/retrieveNewSubmissions.v1.ts +++ b/src/operations/retrieveNewSubmissions.v1.ts @@ -48,9 +48,14 @@ async function v1( function buildResponse(newFormSubmissions: NewFormSubmission[]): { name: string; createdAt: number; + version: number; }[] { return newFormSubmissions.map((item) => { - return { name: item.name, createdAt: item.createdAt }; + return { + name: item.name, + createdAt: item.createdAt, + version: item.version, + }; }); } From 4d81d34740ea495c3f1562651d4bebc11cd92550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Tue, 23 Jun 2026 12:01:19 -0400 Subject: [PATCH 2/9] feat: add version information to retrieveSubmission API response --- src/lib/vault/getFormSubmission.ts | 2 +- src/lib/vault/mappers/formSubmission.mapper.ts | 7 ++++++- src/lib/vault/types/formSubmission.types.ts | 1 + src/operations/retrieveSubmission.v1.ts | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lib/vault/getFormSubmission.ts b/src/lib/vault/getFormSubmission.ts index c70e5361..8ae05ecb 100644 --- a/src/lib/vault/getFormSubmission.ts +++ b/src/lib/vault/getFormSubmission.ts @@ -16,7 +16,7 @@ export async function getFormSubmission( TableName: "Vault", Key: { FormID: formId, NAME_OR_CONF: `NAME#${submissionName}` }, ProjectionExpression: - "CreatedAt,#statusCreatedAtKey,ConfirmationCode,FormSubmission,FormSubmissionHash,SubmissionAttachments", + "CreatedAt,#statusCreatedAtKey,ConfirmationCode,FormSubmission,FormSubmissionHash,SubmissionAttachments,Version", ExpressionAttributeNames: { "#statusCreatedAtKey": "Status#CreatedAt", }, diff --git a/src/lib/vault/mappers/formSubmission.mapper.ts b/src/lib/vault/mappers/formSubmission.mapper.ts index de540535..d9044f0a 100644 --- a/src/lib/vault/mappers/formSubmission.mapper.ts +++ b/src/lib/vault/mappers/formSubmission.mapper.ts @@ -51,6 +51,7 @@ export function mapFormSubmissionFromDynamoDbResponse( response.FormSubmission === undefined || response.FormSubmissionHash === undefined // response.SubmissionAttachments could be undefined if API users are retrieving responses that have been created before we implemented the submission attachments feature + // response.Version could be undefined if API users are retrieving responses that have been created before we implemented the form versioning feature ) { throw new Error("Missing key properties in DynamoDB response"); } @@ -61,8 +62,11 @@ export function mapFormSubmissionFromDynamoDbResponse( typeof response.ConfirmationCode !== "string" || typeof response.FormSubmission !== "string" || typeof response.FormSubmissionHash !== "string" || + // response.SubmissionAttachments could be undefined if API users are retrieving responses that have been created before we implemented the submission attachments feature (response.SubmissionAttachments !== undefined && - typeof response.SubmissionAttachments !== "string") + typeof response.SubmissionAttachments !== "string") || + // response.Version could be undefined if API users are retrieving responses that have been created before we implemented the form versioning feature + (response.Version !== undefined && typeof response.Version !== "number") ) { throw new Error("Unexpected type in DynamoDB response"); } @@ -78,6 +82,7 @@ export function mapFormSubmissionFromDynamoDbResponse( response.SubmissionAttachments, ) : [], + version: response.Version ?? 1, }; } catch (error) { logMessage.info( diff --git a/src/lib/vault/types/formSubmission.types.ts b/src/lib/vault/types/formSubmission.types.ts index ff3f078a..731997ed 100644 --- a/src/lib/vault/types/formSubmission.types.ts +++ b/src/lib/vault/types/formSubmission.types.ts @@ -41,4 +41,5 @@ export type FormSubmission = { answers: string; checksum: string; attachments: PartialAttachment[]; + version: number; }; diff --git a/src/operations/retrieveSubmission.v1.ts b/src/operations/retrieveSubmission.v1.ts index a5117217..5375815c 100644 --- a/src/operations/retrieveSubmission.v1.ts +++ b/src/operations/retrieveSubmission.v1.ts @@ -111,6 +111,7 @@ function buildJsonResponse( md5: attachment.md5, })), }), + version: formSubmission.version, }); } From 0750310bcfe7803302bd0f509e0c35764a74471d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Tue, 23 Jun 2026 14:53:12 -0400 Subject: [PATCH 3/9] feat: enhance retrieveTemplate API operation to allow user to request specific form version --- src/lib/formsClient/getFormTemplate.ts | 36 ++++++++++++++++++++------ src/operations/retrieveTemplate.v1.ts | 12 +++++++-- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/lib/formsClient/getFormTemplate.ts b/src/lib/formsClient/getFormTemplate.ts index 5d738b87..5e1265b2 100644 --- a/src/lib/formsClient/getFormTemplate.ts +++ b/src/lib/formsClient/getFormTemplate.ts @@ -4,16 +4,36 @@ import { logMessage } from "@lib/logging/logger.js"; export async function getFormTemplate( formId: string, + version: number, ): Promise { try { - const template = await prisma.template.findUnique({ - where: { - id: formId, - }, - select: { - jsonConfig: true, - }, - }); + const template = await prisma.templateVersion + .findUnique({ + where: { + templateId_versionNumber: { + templateId: formId, + versionNumber: version, + }, + }, + select: { + jsonConfig: true, + }, + }) + // Fallback query to be deleted once form versioning is fully released in Production + .then((result) => { + if (result !== null) { + return result; + } + + return prisma.template.findUnique({ + where: { + id: formId, + }, + select: { + jsonConfig: true, + }, + }); + }); if (template === null) { return undefined; diff --git a/src/operations/retrieveTemplate.v1.ts b/src/operations/retrieveTemplate.v1.ts index 45bc6ede..3034a06a 100644 --- a/src/operations/retrieveTemplate.v1.ts +++ b/src/operations/retrieveTemplate.v1.ts @@ -17,9 +17,17 @@ async function v1( const serviceUserId = retrieveRequestContextData( RequestContextualStoreKey.serviceUserId, ); + const version = Number(request.query.version ?? 1); try { - const formTemplate = await getFormTemplate(formId); + if (Number.isNaN(version)) { + response + .status(400) + .json({ error: "URL parameter 'version' should be a number" }); + return; + } + + const formTemplate = await getFormTemplate(formId, version); if (formTemplate === undefined) { response.status(404).json({ error: "Form template does not exist" }); @@ -38,7 +46,7 @@ async function v1( } catch (error) { next( new Error( - `[operation] Internal error while retrieving template. Params: formId = ${formId}`, + `[operation] Internal error while retrieving template. Params: formId = ${formId} ; version = ${request.query.version}`, { cause: error }, ), ); From 144d339c72ea90be6cd420fb698bfb831bf45640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Wed, 24 Jun 2026 13:34:32 -0400 Subject: [PATCH 4/9] chore: remove vitest-tsconfig-paths package now that Vitest supports that feature by default --- package.json | 1 - pnpm-lock.yaml | 896 +++++++++++++++++++++++++--------------------- vitest.config.mts | 5 +- 3 files changed, 494 insertions(+), 408 deletions(-) diff --git a/package.json b/package.json index 730235fb..3728145a 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,6 @@ "tsx": "^4.19.1", "typescript": "^5.6.2", "vite": "^8.0.16", - "vite-tsconfig-paths": "^5.0.1", "vitest": "^4.0.0", "vitest-mock-express": "^2.2.0", "vitest-mock-extended": "^4.0.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a18089f..4baa6b22 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,19 +10,19 @@ importers: dependencies: '@aws-sdk/client-dynamodb': specifier: ^3.823.0 - version: 3.1079.0 + version: 3.1075.0 '@aws-sdk/client-s3': specifier: ^3.823.0 - version: 3.1079.0 + version: 3.1075.0 '@aws-sdk/client-sqs': specifier: ^3.823.0 - version: 3.1079.0 + version: 3.1075.0 '@aws-sdk/lib-dynamodb': specifier: ^3.823.0 - version: 3.1079.0(@aws-sdk/client-dynamodb@3.1079.0) + version: 3.1075.0(@aws-sdk/client-dynamodb@3.1075.0) '@aws-sdk/s3-request-presigner': specifier: ^3.859.0 - version: 3.1079.0 + version: 3.1075.0 '@gcforms/database': specifier: 1.1.2 version: 1.1.2(typescript@5.9.3) @@ -56,7 +56,7 @@ importers: devDependencies: '@aws-sdk/types': specifier: ^3.662.0 - version: 3.973.15 + version: 3.973.13 '@biomejs/biome': specifier: ^1.9.0 version: 1.9.4 @@ -83,131 +83,155 @@ importers: version: 7.2.2 tsc-alias: specifier: ^1.8.15 - version: 1.9.0 + version: 1.8.17 tsx: specifier: ^4.19.1 - version: 4.23.0 + version: 4.22.4 typescript: specifier: ^5.6.2 version: 5.9.3 vite: specifier: ^8.0.16 - version: 8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0) - vite-tsconfig-paths: - specifier: ^5.0.1 - version: 5.1.4(typescript@5.9.3)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)) + version: 8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4) vitest: specifier: ^4.0.0 - version: 4.1.9(@types/node@22.20.0)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)) + version: 4.1.9(@types/node@22.20.0)(vite@8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4)) vitest-mock-express: specifier: ^2.2.0 version: 2.2.0 vitest-mock-extended: specifier: ^4.0.0 - version: 4.0.0(typescript@5.9.3)(vitest@4.1.9(@types/node@22.20.0)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0))) + version: 4.0.0(typescript@5.9.3)(vitest@4.1.9(@types/node@22.20.0)(vite@8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4))) packages: - '@aws-sdk/checksums@3.1000.12': - resolution: {integrity: sha512-RgNDWfhNRIlNEzePIRrYTNi/6q+wwRMMapojn8YVzw4ZcJRa/gxVMtUbeZARR1gmopuv6oIhMbY7J66qIQ0ynw==} + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/crc32c@5.2.0': + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} + + '@aws-crypto/sha1-browser@5.2.0': + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/checksums@3.1000.8': + resolution: {integrity: sha512-v0U9S7gBIme3OTgt1LdbAF4RpvavCc+4GK1+1xqAcqtbrHsEhjQo6R45LKcjhs/+WrRJij1Y0Gztw7QPAIeUfA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-dynamodb@3.1079.0': - resolution: {integrity: sha512-njnQvv5lqyzX42Af/Z3nuxm6eK9/OPDYkaIah3m2sJoudAKkvvJ5jOTAtw8zGhu5zviT4Sa9giYC1FHkabuAFA==} + '@aws-sdk/client-dynamodb@3.1075.0': + resolution: {integrity: sha512-3KlTXh6U2nDqL+epT1XdxnszLtCEAvoeO7phI4UGiQeKMiibcyBsJvSlyEj1tBoNOsbdcmp1QLM8za415sDzzQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-s3@3.1079.0': - resolution: {integrity: sha512-di9U/7Po7qlVYb2dq58ULsbBAE1pBIk53rux+50LQCvH1X+/l1Ys+BIk/QLBtdaK1nADk0xRNEBbA1QWVnMccw==} + '@aws-sdk/client-s3@3.1075.0': + resolution: {integrity: sha512-h1A6nIl1YX6Y45enGsTK7ef3ZrOnBiQJ1qF5R2K/nMWfsu6A9mc2Y5T66nxerABzyjjyyvign3MrzafnFoQKmA==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-secrets-manager@3.1079.0': - resolution: {integrity: sha512-BnN3yTP28Z+Ac3bsGpVTHPQVpLFFs1tSVJ+QxaWJsvb3curmlGTCHXCGxPSpk+NzzbOfwjE8ZA6NnU/orLr9Gw==} + '@aws-sdk/client-secrets-manager@3.1075.0': + resolution: {integrity: sha512-5cLjSmrgzohO2q4gMrb7oHq58W+gR/qul7yHSRZ1fZv7aYtONvq23dKr+E7i0KBid4zkjGpjw8VJ7fNdQi9YUQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/client-sqs@3.1079.0': - resolution: {integrity: sha512-8otd3BCGQGKvAXfsKORdOpDLndDjgEGmw2RmPWmi8lY/B/v1u41ElzcBYnjDWLivwIFVuJfbxrVSJlv5WFm0hA==} + '@aws-sdk/client-sqs@3.1075.0': + resolution: {integrity: sha512-ZHowzLHFTIz482Z98Y8GtszLN7Q1YvC74xxExwr2rbKJeNWTXHVoMVwlq/jv5Kyf0elVAGmoID12Gf6aSdWy0Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.974.27': - resolution: {integrity: sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA==} + '@aws-sdk/core@3.974.23': + resolution: {integrity: sha512-MiWR/uWjxjFXGzrE0Ghc5lWxUxzHsUWFhV+OX7M4cR9SrmrnZs6TXavnCWnzzdwJeFri34xQo81rvGNzK3c4BQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.53': - resolution: {integrity: sha512-+KDA3uc/HZ1vIneGu5QMQb0gAXDYrm2vOE60+BJ7lS0YinMQ5i2oV4PR1A16XkF6K1IbSwjEHd1hQIIgMsK48w==} + '@aws-sdk/credential-provider-env@3.972.49': + resolution: {integrity: sha512-liB3yQNHCM9k/gu/w36XHMKPluT7HTlnGUhRbBGSISDQkcr/Sy1zsZabiuvQj8WG5yW573u9RehrBvvnIQ9OEQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.55': - resolution: {integrity: sha512-1gBfkWY3RWeBlCoB9lIJjXMx45/54wxcgfzv6BY9otTmMrZPcNPi1v+MwZxxaCUg441NV3jsr1efnFNCXiW70g==} + '@aws-sdk/credential-provider-http@3.972.51': + resolution: {integrity: sha512-XET0H2oofciJ5lMRWNIvRjAP7Q3wv2XT+JtJJEdhPWUMwe3TvQ9qcxonpu7vXmNngncvFpi4E2It+Tamas/naA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.972.60': - resolution: {integrity: sha512-CV2md+PXvABwRjApWGhQ0wACy9WSFIhnUGrovLcjnjBCd/46TbuivLADtkF8IWNjtCQmQ+2IagSaxqBYqXBNAQ==} + '@aws-sdk/credential-provider-ini@3.972.56': + resolution: {integrity: sha512-IAmc61hbgQiHht9U3x0tnRwz0lzdwOwD/i9voRgdJrKamF+JtmrBOsW9GwB7mfFonNWOWL4qARWYrF8veEMe3w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.59': - resolution: {integrity: sha512-JG4S9yyA1GFzJdJXqLKrUzZbyK+VDp2QIsJD7YOicJHAhqymfHpDJIok2dLnhOdVB0I37RjdC53uOwCMVS00gw==} + '@aws-sdk/credential-provider-login@3.972.55': + resolution: {integrity: sha512-hBBkANo3cDn+h2qxxzER4a+J8JCO9o9Z/YYmU7iky6AcaarX5RRdRcHNC6SLdwY0vAXQygn6soUbDqPn3GghaA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.62': - resolution: {integrity: sha512-S6Slq3Tx7bvFk5yc34XNADyZYTX2HUXvaFAnowGRQnhjBO8J/mP62Fn7lxvJwjaDyYm/7gh9h6HEHaltRyMFXw==} + '@aws-sdk/credential-provider-node@3.972.58': + resolution: {integrity: sha512-OyCLVmSI7pZO8hxwNVX6pXhTVlJqRBTp+ijdEfJSUj0RyjHnF602OfAarOzGq6wkGodeFkYBt8MmJ6A6ycRgWw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.53': - resolution: {integrity: sha512-EhfH+MQlqOMCkXIVa8MMObPzAQqwTTtxA7KhEJiyPeuNVA8PLOOUpgK7nBrgaDaGiIDLN/9LpGdaHuDjomeRTw==} + '@aws-sdk/credential-provider-process@3.972.49': + resolution: {integrity: sha512-C8h36lBuC/RnBSsjlO+dn6xZm3KbAl5vpJaVPAfQnMmz2/OISmKOc8XZcqMQgO2ADwBYNRMM6Kf3vz9G/TulMQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.59': - resolution: {integrity: sha512-h8793pOjcImx0SB+VcLONcaQQ57VAvKVuqyewQMRKqqH+CSXsG2dwOeLMUJPMxLdNvL7dXOM0ueTukyNUnu5mA==} + '@aws-sdk/credential-provider-sso@3.972.55': + resolution: {integrity: sha512-1FkOz74Ea5QGS9jtIoXp55T/IkSS3spv+nLTT07fRY/+T5xmEOqaYBVIaEmX4zTNvbV6g2lrtlaVKWEoNyJt3w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.59': - resolution: {integrity: sha512-VoyO9+vl3XVmpZwn4obskrWIkrA/Jf3lSe1E3ZERlaN9u0D4YZ6+HywC3+L98QOXqZesEfedk67gRER8tK8+8w==} + '@aws-sdk/credential-provider-web-identity@3.972.55': + resolution: {integrity: sha512-g2BoECD1q01kTPByi56+VLVvdWDzMkKIcr77qixpqH0okw2t0U5CoPv+6S8v/D1Y2Wa6QKKtn6XAtDzP+Kfpvg==} engines: {node: '>=20.0.0'} - '@aws-sdk/dynamodb-codec@3.973.27': - resolution: {integrity: sha512-eOTdNw3SwpkO/WOBFFY28Us9WcjBxejRw0vRD0eRqp6+aisHnBXiyQhSX2VIPHkCMFThhBRfSftdXBbgh95y8A==} + '@aws-sdk/dynamodb-codec@3.973.23': + resolution: {integrity: sha512-GFfrjNXw+QteWbum8jD22G3T0FD/XiJEGp6r1CoqndMc6pxyQFoQ8nqTuNn1rbqYwqv4iCTl7GYoB9H17REKzw==} engines: {node: '>=20.0.0'} '@aws-sdk/endpoint-cache@3.972.8': resolution: {integrity: sha512-bBmkG0Dnhfq0/T4Z0PpUr7HkncBVaWvvCbvafeaUM+yC9wa8GGjLJmonq0QL17REB9WivgGeYgWQ5A80Uw5UnQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/lib-dynamodb@3.1079.0': - resolution: {integrity: sha512-iq6nn4zfFs79sbfYHQf3Suh2XcBHP2Hlu48XAZHOlIJBok+IMETv+WVAXHktlyAwYyNHjG9iW8Flupuj4jMvAA==} + '@aws-sdk/lib-dynamodb@3.1075.0': + resolution: {integrity: sha512-3OxmMDgk8wvK6QOaVrQuOq9t6xlgS5047aDPxAZxTSwGBcEMc6FtiamtoK3kfClfOt7k3t+NWIo0bIfhWQ4Pzg==} engines: {node: '>=20.0.0'} peerDependencies: - '@aws-sdk/client-dynamodb': ^3.1079.0 + '@aws-sdk/client-dynamodb': ^3.1075.0 - '@aws-sdk/middleware-endpoint-discovery@3.972.22': - resolution: {integrity: sha512-GMoLg4XAnkiwevqcOfgz0lOTYmIdM7MJK/BL9EAvsoMFqKIGRpyNIvuSNg5gdFzP57yB+EklMlK0+TwBqj1tCg==} + '@aws-sdk/middleware-endpoint-discovery@3.972.19': + resolution: {integrity: sha512-FMgyzUq3Jh+ONRYxryBRNdBd+FUX8PwRl07ccQknNdoms6KCeAEusCkl6whqpDrPQ6OH0ddeSifKyqYSs2DLIw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.58': - resolution: {integrity: sha512-6uaWRRYJGhOqc9EoTSbLDf9nI/doSAb5vAwGshs5/Hlv5Ce25b246lBkbRd/77fLAi+uMI1a70mJzVyLyCEufQ==} + '@aws-sdk/middleware-flexible-checksums@3.974.33': + resolution: {integrity: sha512-qMgQSPemQq2/eW/e/0+SpY4kYR5L7dUgBiVdEc5bd+ztHNv07ZMYiI+sTiir3TgKndFfglSw/VFi7oZJ6bZ63g==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-sqs@3.972.34': - resolution: {integrity: sha512-BgCMs873RWtMe8LlNY5hxJjVbZtaHR6nY3BtQZk14drRJb3Iqecp5VADpw3eF5cnBvlZLWblAjCjJFU1mTjoeQ==} + '@aws-sdk/middleware-sdk-s3@3.972.54': + resolution: {integrity: sha512-GDfDQ0gwLFRKN9gWIKcmVrHJ3e7XagnY7N1LLzMVNgnOnuY7f/ALgmy3CuBjosWD95T/Z6e+gs1IeWmLPkyLKQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.997.27': - resolution: {integrity: sha512-A8PIePF9NIIOJ/4Lg1rl9xm/+QaKkHGetq+Z9wb5B+3Da31YYXRo8n7IDMh5C+HQI5eyEmjrwkGWVdYtnLtbXQ==} + '@aws-sdk/middleware-sdk-sqs@3.972.31': + resolution: {integrity: sha512-56ifsBmK9bLn5EE/t6c0nmjOB1BO8cJDLkA1VOlsN1GR85ROqnaCwVDspqcwsLaBDgPlwyYNedoDIoT3t6Ho1A==} engines: {node: '>=20.0.0'} - '@aws-sdk/s3-request-presigner@3.1079.0': - resolution: {integrity: sha512-NfHUaND7WyLUPkO7HCF3MFg4bdscY34A4tm4dPWa31qYzhGNZarRPr/CcRgllxzPoOSD/EHfZ4fQtZnMl2xWFg==} + '@aws-sdk/nested-clients@3.997.23': + resolution: {integrity: sha512-gO93ZPsI2bxeFZD42f1/qjDw6FAZkNZcKRO94LIiT03fzOmcJ9e/tunxjVjA1Rl69ClmVJzz8H3G9CdKef10PA==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.996.38': - resolution: {integrity: sha512-C379Sk+MiFZCfWZphKlMyLHKxV22OjoGM5KJjj5IJNJcOCWL4IGIpnEGzv1FQiRwhYXfq55SJMfxlqPE08JJ9g==} + '@aws-sdk/s3-request-presigner@3.1075.0': + resolution: {integrity: sha512-++ftTvAGZSTuzFVHEPk8lLi7mybBD8PzJ9USWBvwnE4kSrXOyqYVJ5Ixd06xUEWS/xsrhpkI07mzCLGIxrRymA==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1079.0': - resolution: {integrity: sha512-cbietrLlHPhhmbnMPTuDS4Zj/KNGhY+3vVhn6dwjO6Dqzrwothzg2srtcY34T9mlICsTXn34avDoWLHSntP54A==} + '@aws-sdk/signature-v4-multi-region@3.996.35': + resolution: {integrity: sha512-6L/VWs+Wch2stHemCGTmUNqKLMzURxQDK5boNG3Jn3kAOp71meDUuS5sbObpEvFxHDq0uWeSLFDNSYsjNt+Dlg==} engines: {node: '>=20.0.0'} - '@aws-sdk/types@3.973.15': - resolution: {integrity: sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ==} + '@aws-sdk/token-providers@3.1074.0': + resolution: {integrity: sha512-pv80IzgGW4RnXWtft692chZOM9i6PhebVsLCcnaM4dBEPZva2fE6FXAHs76G7Rc7s3yGyX/68G0nZMrUy+Vmpg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.973.13': + resolution: {integrity: sha512-pEHZqRkAlHfnfAU9tK+WpKv/gBNjGJrHMgA3A0iYRGyswBS2t0pfez+lWlwktb3Bqa0ovh7w/QJTFwp3fDxLNg==} engines: {node: '>=20.0.0'} '@aws-sdk/util-dynamodb@3.996.5': @@ -216,12 +240,16 @@ packages: peerDependencies: '@aws-sdk/client-dynamodb': ^3.1069.0 - '@aws-sdk/xml-builder@3.972.33': - resolution: {integrity: sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A==} + '@aws-sdk/util-locate-window@3.965.8': + resolution: {integrity: sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/xml-builder@3.972.31': + resolution: {integrity: sha512-SzE4Pgyl+hDF+BuyuzxUSpwnuUu9lJuO1YGgteG89/4Qv0+2IQiVQqdbPV32IozLvXWQChPQcdkk/sKvb1QHiQ==} engines: {node: '>=20.0.0'} - '@aws/lambda-invoke-store@0.3.0': - resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} + '@aws/lambda-invoke-store@0.2.4': + resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==} engines: {node: '>=18.0.0'} '@biomejs/biome@1.9.4': @@ -477,8 +505,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@oxc-project/types@0.138.0': - resolution: {integrity: sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA==} + '@oxc-project/types@0.137.0': + resolution: {integrity: sha512-WT+Gb24i8hmvo85AIv2oEYouEXkRlKAlT9WaCa3TfLgNCN+GhrJOGZuIlMouAh38Qe4QOx26eUOVsq70qXrywA==} '@paralleldrive/cuid2@2.3.1': resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} @@ -539,97 +567,97 @@ packages: peerDependencies: '@redis/client': ^1.0.0 - '@rolldown/binding-android-arm64@1.1.4': - resolution: {integrity: sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw==} + '@rolldown/binding-android-arm64@1.1.3': + resolution: {integrity: sha512-DT6Z3PhvioeHMvxo+xHc3KtqggrI7CCTXCmC2h/5zUlp5jVitv7XEy+9q5/7v8IolhlioawpMo8Kg0EEBy7J0g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rolldown/binding-darwin-arm64@1.1.4': - resolution: {integrity: sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ==} + '@rolldown/binding-darwin-arm64@1.1.3': + resolution: {integrity: sha512-0NwgwsjM7LrsuVnXMK3koTpagBNOhloc/BNjKqZjv4V5zI5r13qx69uVhRx+o5Z0yy4Hzq+lpy7TAgUG/ocvrw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rolldown/binding-darwin-x64@1.1.4': - resolution: {integrity: sha512-F7hHC3gwY11+vByKPRWqwGbeXWVgKmL+pTGCinaEhdihzBV2aQ0fvZOch9cXYUOKuKKq429HeYXOqQLc7wFCEg==} + '@rolldown/binding-darwin-x64@1.1.3': + resolution: {integrity: sha512-YtiBp4disu6V560loT6PjMdiRaWmVvDNrUunAalbiFx2ggeJwxdAsgZMcoGP17uyAsTwAj5V1niksxlHnVQ1Sw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rolldown/binding-freebsd-x64@1.1.4': - resolution: {integrity: sha512-sI5yw+7s92SK6odiEhD5lKCBlWcpjHS5qyqpVQbZAJ0fIzEUXrmbl3DH2ybR3PZogulNJF+COLtmA8hUfvkCCQ==} + '@rolldown/binding-freebsd-x64@1.1.3': + resolution: {integrity: sha512-yD3EkEdXk2LypPxnf/kSZHirarsI8gcPzc62SukhR9VJTyvV+F9Q/GxWNuCojc7sXyuVC4DxRGhdDK4X8VSsbw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rolldown/binding-linux-arm-gnueabihf@1.1.4': - resolution: {integrity: sha512-mCi0OKgEieFircrtVYmQAFGszRtMnZ6fpZAXrxanXAu7lqZcsK1E1RAaZNG0uKAnxox3B1f4EyQNnoyMfN1vAA==} + '@rolldown/binding-linux-arm-gnueabihf@1.1.3': + resolution: {integrity: sha512-c+8vieQbsD7HNAHKIA34w0GJ9FedFFuJGD+7E6vz7Q3uqAIugL5p45fhlsj4UaAsHpcmlqugBWMhA0/j7o0sIg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - '@rolldown/binding-linux-arm64-gnu@1.1.4': - resolution: {integrity: sha512-B9Ial3Kv5sh0SHnB1g/QWcUQCEvCF6QKGAl4zXypYj65mVI+B4AhFBwPtSN7pDrJeIx8Z7zdy4ntx+wQABom7w==} + '@rolldown/binding-linux-arm64-gnu@1.1.3': + resolution: {integrity: sha512-50jD0uUwLvur7Zz9LHz17kaAdTPjn5wN93hEgjvmYFRZwiR7ZJYovTd5ipyWJDAnXKvZ+wgc+/Ika6dwSF5OcA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-arm64-musl@1.1.4': - resolution: {integrity: sha512-lZVym0PuHE1KZ22gmFTC15lAkrg9iTszR617oYRB/iPY1A56ywoJzVKOJBKaot5RiikCObmur6pogpse3gRcng==} + '@rolldown/binding-linux-arm64-musl@1.1.3': + resolution: {integrity: sha512-BO9+oPL8K9poZJBfYPsXNtYjPE5uM3qeehT3aFcW4LITOl+iSqhp0abzjR2nWBUNjIZeKXjAEWBZ64WjNoHd6w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rolldown/binding-linux-ppc64-gnu@1.1.4': - resolution: {integrity: sha512-t2DNiLJWNTbnEHyUzTumldML6ET4/g16467LZoDDJ3tSxGvguL5/NyC2lCsNKuyRycg9XeDQF5SSv+TNOhQEXg==} + '@rolldown/binding-linux-ppc64-gnu@1.1.3': + resolution: {integrity: sha512-f3VpLB1vQ0Eo6ecr/6cekLnvYMFF4YBFoVGkfkvPLq1bAkbAwHYQPZKoAmG6OJyTcxxoC+AvezGx/S1obNC0Mw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-s390x-gnu@1.1.4': - resolution: {integrity: sha512-0WIRnL1Uw4BvTZRLQt+PVgo6ZKTJadlC2btP+/EOXv2f/DWbY0rEgl+y834mIVwP1FkTlWVTrGGJXf12lru7EQ==} + '@rolldown/binding-linux-s390x-gnu@1.1.3': + resolution: {integrity: sha512-AmurZ26Pqx/RI9N1gzEOCklkKXl927yjfXWUUS0O7Puh8ARM/Ob8qfrD3qnWksScdw6cSrW5PSHE9DyLu7+PtA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-gnu@1.1.4': - resolution: {integrity: sha512-JWtGshGfX+oENAKonoNkqEJX+7hC8yfhi9GUyPX1VX4mdh1y5r+ZiJLR5XzAB0aoP6s/PcILsGjKq8O0mm24bw==} + '@rolldown/binding-linux-x64-gnu@1.1.3': + resolution: {integrity: sha512-JJpqs8bRGITDOdbkNKnlojzBabbOHrqjSvDr0IVsZObE1lBcPjxItUEY9eWIDbxaJ3cGrXPWGfGkIxFijg/URg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rolldown/binding-linux-x64-musl@1.1.4': - resolution: {integrity: sha512-rT6yQcxUuXs4CnbofqwHRRV0iem349rLMYpTjkgQGLjrY4ado/eDzwPZPTCgTOlF6Nkp8NEv70yLMTn6qkWxsQ==} + '@rolldown/binding-linux-x64-musl@1.1.3': + resolution: {integrity: sha512-rSJcdjPxzA/by/6/rYs+v+bXU7UjvnbUWz8MJb6kh6+knqB1dCrtHg0uu7C/4haqJvqdkYHQ5IGn+tCH9GLW/g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rolldown/binding-openharmony-arm64@1.1.4': - resolution: {integrity: sha512-KXMGoboq5cyaCQjDA4GLuRiOwBQ0EyFnJoVViLeZ45/3rFItRODEr+NdsBcVpll40hhNArlm/speWGRvj08LzA==} + '@rolldown/binding-openharmony-arm64@1.1.3': + resolution: {integrity: sha512-hQ3/PYkDJICgevvyNcVrihVeqq7k1Pp3VZ9lY+dauAYUJKO+auqApvANhvR1An9BhmqYKvW2Mu1F9u4DXSMLxQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rolldown/binding-wasm32-wasi@1.1.4': - resolution: {integrity: sha512-5K83rb36oJiY7BCyE9zLZtGcPV4g5wvq+xwdO0XPIwDVZI8cyB/AUjkNXGb92/rnmezEkjMOpgY61rtwjQtFwg==} + '@rolldown/binding-wasm32-wasi@1.1.3': + resolution: {integrity: sha512-Elcv/BtML9lXrV6JuKITc/grN2kYV9gjsQpW8Jfw4ioK0TOkjBjye0nnyqQNy9STNaI20lXNaQBRrD5gSgR0Yg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] - '@rolldown/binding-win32-arm64-msvc@1.1.4': - resolution: {integrity: sha512-PnWBtw3TV5KOg69HQQDR0mnQuyCmSGR2pAB4DC1rPF808fgKeTUMj2EOEyKATpgiuxuR5APQmiDO7PDgEjTFSA==} + '@rolldown/binding-win32-arm64-msvc@1.1.3': + resolution: {integrity: sha512-2DrEfhluH9yhiaFApmsjsjwrSYbNcY1oFTzYSP1a535jDbV98zCFanA/96TBUd0iDFcxGmw9QRExwGCXz3U+/g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - '@rolldown/binding-win32-x64-msvc@1.1.4': - resolution: {integrity: sha512-M1lpniBePobTfsa7Ks9a199e1akxsXn+GYBUKsEzv3YFzOm1HJAMNwKI3qr0Zq+mxwx9gOZoTdP1yXRYsZUocQ==} + '@rolldown/binding-win32-x64-msvc@1.1.3': + resolution: {integrity: sha512-OL4OMk7UPXOeVGGd3qo5zJyPIljf4AFgk5QAkPPS+OoLuOOozhuaQGC18MxVTnw/06q93gShAJzlwnSCY9YtqA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] @@ -656,30 +684,42 @@ packages: '@sinonjs/samsam@8.0.3': resolution: {integrity: sha512-hw6HbX+GyVZzmaYNh82Ecj1vdGZrqVIn/keDTg63IgAwiQPO+xCz99uG6Woqgb4tM0mUiFENKZ4cqd7IX94AXQ==} - '@smithy/core@3.29.1': - resolution: {integrity: sha512-qoiY4nrk5OCu1+eIR1VB8l5DmON/oKiqrd5zZFAhXJXjJlLWQusKEW/SkBDAtGDcPaz86m9kfcE1lngU0GlM6A==} + '@smithy/core@3.26.0': + resolution: {integrity: sha512-mLUktFAn+Pa2agl1J7VgtYNFWCX8/b4GMJSK1hCu4YCvtBfM6F8Os3EP4ry+DFFlXOf3wyvlgXhuUdFoy52D3g==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.4.6': - resolution: {integrity: sha512-B2WQ/PV/H6Jeg3lrIq6bKUfa6Hy01mtK7CGs6lhjzHA6k4aagldH6T6eEjnzKl4HI0cJnAsxfJ19pgb5PV+CVQ==} + '@smithy/credential-provider-imds@4.4.2': + resolution: {integrity: sha512-18UMDMyrAbDcpmL1gLUA7ww0fRTcdCrSjSJOi2Sbld+tVjwD/pW+OAwjlScFLR7vvBnhZrIPQ7kVuTf1mnJLug==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.6.3': - resolution: {integrity: sha512-CwCc/7SMTj45y97MUnDTbTaxvtAsiNNRm81z3abROIuMbMsC2Iy5EKfkkVdsKrz8WExQAAMx1EJapq+9j4fFTQ==} + '@smithy/fetch-http-handler@5.5.2': + resolution: {integrity: sha512-Ei/UK/QMhq0rKaMqGPlOAkE2yS9DZeYmZdk1RAKc3vp3zxgleZHZyBLlZv8yLsxljX4svCRuMTD6u3LLIcU4Bg==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.9.3': - resolution: {integrity: sha512-qZTa4gQFUo8RM02rk6q5UVTDLNrQ1oS20LsepBzqq1QBVc/EHJ03OOUADcqMZiXHArW+Y7+OGY0BpdTwZRq/Yg==} + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/node-http-handler@4.8.2': + resolution: {integrity: sha512-wfl1uwrAqMH9/pi4kqBo5LBcFwrJLxuDLqL7p7qNcJIFcyZDUc6pzhYk4CYv+DP7fIUpQCZumwNnkhPKS52osQ==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.6.2': - resolution: {integrity: sha512-QgHflghMoPxCJ9axiCVh8KZfbC9fuP6vkXXyK//E3cq7nLaSSyyLj0GAoqVWezYeDQmXIZhmlRvLE16jsqDK6g==} + '@smithy/signature-v4@5.5.2': + resolution: {integrity: sha512-7xHpmPY4rt0IOmeAA8EfjgEH8isT+587TCdy9H6a7d4OMi5CQ0oEHhWllunvPu4j4Cq0vTFwdxXN/kABWPjdyA==} engines: {node: '>=18.0.0'} - '@smithy/types@4.15.1': - resolution: {integrity: sha512-x3L0XSACF6UYzKpa9biqiRMgvH5+wnFFew9Tm/grFYqgaupPwx/+ojDPpPJM8dZON3S9tjz5U+PQYsCBd1Mw5Q==} + '@smithy/types@4.15.0': + resolution: {integrity: sha512-Z5TAOxygoFvybJV3igo5SloFflSokHx2hu1eFA+DxDTcn+FtKxUSui+rbTRG1pAafMA888Z3MVvCWUuvCrTXjg==} engines: {node: '>=18.0.0'} + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} @@ -1000,8 +1040,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@2.3.0: - resolution: {integrity: sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} @@ -1131,9 +1171,6 @@ packages: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} - globrex@0.1.2: - resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -1476,8 +1513,8 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} - picomatch@4.0.5: - resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} pino-abstract-transport@2.0.0: @@ -1498,8 +1535,8 @@ packages: resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==} engines: {node: '>=12'} - postcss@8.5.16: - resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==} + postcss@8.5.15: + resolution: {integrity: sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==} engines: {node: ^10 || ^12 || >=14} postgres-array@2.0.0: @@ -1594,8 +1631,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rolldown@1.1.4: - resolution: {integrity: sha512-IjZYiLxZwpnhwhdBH2ugdTGVSdhCQUmLxLoqyjiL0JxYjyRst+5a0P3xfrTxJ5F638j4Mvvw5FAX5XE6eHpXbA==} + rolldown@1.1.3: + resolution: {integrity: sha512-1F1eEtUBtFvcGm1HQ9TiUIUHPQG7mSAODrhIzjxoUEFuo8OcbrGLiVLkevNgj84TE4lnHvnumwFjhJO5Eu135g==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -1726,27 +1763,16 @@ packages: typescript: optional: true - tsc-alias@1.9.0: - resolution: {integrity: sha512-IZrCInovKxVCwXyKhcdr/HaxSYugKT0w4zyktOE/4115Nzo6gbp/NhkaEeyOG0/H7QoTeXtv+3UHffBYta9oWw==} + tsc-alias@1.8.17: + resolution: {integrity: sha512-EIduCZHqbNwPm8BZYfq1aD7BQ697A4h6uSGMOFQfYGoQwfrYFTKwYfy9Bv42YxHkduVBcn9Zx0DkX111DKskyg==} engines: {node: '>=16.20.2'} hasBin: true - tsconfck@3.1.6: - resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==} - engines: {node: ^18 || >=20} - deprecated: unmaintained - hasBin: true - peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true - tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.23.0: - resolution: {integrity: sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==} + tsx@4.22.4: + resolution: {integrity: sha512-X8EX+XV4QR5xCsrgxaED954zTDfY8KqlDtskKEL0cHhyS/P8b4IFOvGDQpsC9Q1XnLq915wEfwwY/zzskCtmhg==} engines: {node: '>=18.0.0'} hasBin: true @@ -1790,16 +1816,8 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vite-tsconfig-paths@5.1.4: - resolution: {integrity: sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==} - peerDependencies: - vite: '*' - peerDependenciesMeta: - vite: - optional: true - - vite@8.1.3: - resolution: {integrity: sha512-Ds+gBRbj0lwRO2Y5hwnUBdxSwlAve9LeRyU4sNnAr0ewW0gWF0n5bgXgUzbgZ49MV9BVUAQUFYVcDUcilUExMA==} + vite@8.1.0: + resolution: {integrity: sha512-BuJcQK/56NQTWDGn4ABea3q4SSBdNPWwNZKTkkUpcMPnLoquSYH8llRtSUIgoL1KSCpHt5eghLShn50mH36y7Q==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -1908,164 +1926,223 @@ packages: snapshots: - '@aws-sdk/checksums@3.1000.12': + '@aws-crypto/crc32@5.2.0': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.13 tslib: 2.8.1 - '@aws-sdk/client-dynamodb@3.1079.0': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/credential-provider-node': 3.972.62 - '@aws-sdk/dynamodb-codec': 3.973.27 - '@aws-sdk/middleware-endpoint-discovery': 3.972.22 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.9.3 - '@smithy/types': 4.15.1 + '@aws-crypto/crc32c@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.13 tslib: 2.8.1 - '@aws-sdk/client-s3@3.1079.0': - dependencies: - '@aws-sdk/checksums': 3.1000.12 - '@aws-sdk/core': 3.974.27 - '@aws-sdk/credential-provider-node': 3.972.62 - '@aws-sdk/middleware-sdk-s3': 3.972.58 - '@aws-sdk/signature-v4-multi-region': 3.996.38 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.9.3 - '@smithy/types': 4.15.1 + '@aws-crypto/sha1-browser@5.2.0': + dependencies: + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.13 + '@aws-sdk/util-locate-window': 3.965.8 + '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-secrets-manager@3.1079.0': + '@aws-crypto/sha256-browser@5.2.0': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/credential-provider-node': 3.972.62 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.9.3 - '@smithy/types': 4.15.1 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.13 + '@aws-sdk/util-locate-window': 3.965.8 + '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-sqs@3.1079.0': + '@aws-crypto/sha256-js@5.2.0': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/credential-provider-node': 3.972.62 - '@aws-sdk/middleware-sdk-sqs': 3.972.34 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.9.3 - '@smithy/types': 4.15.1 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.973.13 tslib: 2.8.1 - '@aws-sdk/core@3.974.27': + '@aws-crypto/supports-web-crypto@5.2.0': dependencies: - '@aws-sdk/types': 3.973.15 - '@aws-sdk/xml-builder': 3.972.33 - '@aws/lambda-invoke-store': 0.3.0 - '@smithy/core': 3.29.1 - '@smithy/signature-v4': 5.6.2 - '@smithy/types': 4.15.1 + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.973.13 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/checksums@3.1000.8': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/client-dynamodb@3.1075.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/dynamodb-codec': 3.973.23 + '@aws-sdk/middleware-endpoint-discovery': 3.972.19 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.8.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/client-s3@3.1075.0': + dependencies: + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/middleware-flexible-checksums': 3.974.33 + '@aws-sdk/middleware-sdk-s3': 3.972.54 + '@aws-sdk/signature-v4-multi-region': 3.996.35 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.8.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/client-secrets-manager@3.1075.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.8.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/client-sqs@3.1075.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-node': 3.972.58 + '@aws-sdk/middleware-sdk-sqs': 3.972.31 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.8.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/core@3.974.23': + dependencies: + '@aws-sdk/types': 3.973.13 + '@aws-sdk/xml-builder': 3.972.31 + '@aws/lambda-invoke-store': 0.2.4 + '@smithy/core': 3.26.0 + '@smithy/signature-v4': 5.5.2 + '@smithy/types': 4.15.0 bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.53': + '@aws-sdk/credential-provider-env@3.972.49': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.55': + '@aws-sdk/credential-provider-http@3.972.51': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.9.3 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.8.2 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.972.60': - dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/credential-provider-env': 3.972.53 - '@aws-sdk/credential-provider-http': 3.972.55 - '@aws-sdk/credential-provider-login': 3.972.59 - '@aws-sdk/credential-provider-process': 3.972.53 - '@aws-sdk/credential-provider-sso': 3.972.59 - '@aws-sdk/credential-provider-web-identity': 3.972.59 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/credential-provider-imds': 4.4.6 - '@smithy/types': 4.15.1 + '@aws-sdk/credential-provider-ini@3.972.56': + dependencies: + '@aws-sdk/core': 3.974.23 + '@aws-sdk/credential-provider-env': 3.972.49 + '@aws-sdk/credential-provider-http': 3.972.51 + '@aws-sdk/credential-provider-login': 3.972.55 + '@aws-sdk/credential-provider-process': 3.972.49 + '@aws-sdk/credential-provider-sso': 3.972.55 + '@aws-sdk/credential-provider-web-identity': 3.972.55 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/credential-provider-imds': 4.4.2 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-login@3.972.59': + '@aws-sdk/credential-provider-login@3.972.55': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-node@3.972.62': - dependencies: - '@aws-sdk/credential-provider-env': 3.972.53 - '@aws-sdk/credential-provider-http': 3.972.55 - '@aws-sdk/credential-provider-ini': 3.972.60 - '@aws-sdk/credential-provider-process': 3.972.53 - '@aws-sdk/credential-provider-sso': 3.972.59 - '@aws-sdk/credential-provider-web-identity': 3.972.59 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/credential-provider-imds': 4.4.6 - '@smithy/types': 4.15.1 + '@aws-sdk/credential-provider-node@3.972.58': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.49 + '@aws-sdk/credential-provider-http': 3.972.51 + '@aws-sdk/credential-provider-ini': 3.972.56 + '@aws-sdk/credential-provider-process': 3.972.49 + '@aws-sdk/credential-provider-sso': 3.972.55 + '@aws-sdk/credential-provider-web-identity': 3.972.55 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/credential-provider-imds': 4.4.2 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-process@3.972.53': + '@aws-sdk/credential-provider-process@3.972.49': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.972.59': + '@aws-sdk/credential-provider-sso@3.972.55': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/token-providers': 3.1079.0 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/token-providers': 3.1074.0 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-web-identity@3.972.59': + '@aws-sdk/credential-provider-web-identity@3.972.55': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/dynamodb-codec@3.973.27': + '@aws-sdk/dynamodb-codec@3.973.23': dependencies: - '@aws-sdk/core': 3.974.27 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 '@aws-sdk/endpoint-cache@3.972.8': @@ -2073,91 +2150,102 @@ snapshots: mnemonist: 0.38.3 tslib: 2.8.1 - '@aws-sdk/lib-dynamodb@3.1079.0(@aws-sdk/client-dynamodb@3.1079.0)': + '@aws-sdk/lib-dynamodb@3.1075.0(@aws-sdk/client-dynamodb@3.1075.0)': dependencies: - '@aws-sdk/client-dynamodb': 3.1079.0 - '@aws-sdk/core': 3.974.27 - '@aws-sdk/util-dynamodb': 3.996.5(@aws-sdk/client-dynamodb@3.1079.0) - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/client-dynamodb': 3.1075.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/util-dynamodb': 3.996.5(@aws-sdk/client-dynamodb@3.1075.0) + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/middleware-endpoint-discovery@3.972.22': + '@aws-sdk/middleware-endpoint-discovery@3.972.19': dependencies: '@aws-sdk/endpoint-cache': 3.972.8 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.58': + '@aws-sdk/middleware-flexible-checksums@3.974.33': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/signature-v4-multi-region': 3.996.38 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/checksums': 3.1000.8 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-sqs@3.972.34': + '@aws-sdk/middleware-sdk-s3@3.972.54': dependencies: - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/signature-v4-multi-region': 3.996.35 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.27': + '@aws-sdk/middleware-sdk-sqs@3.972.31': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/signature-v4-multi-region': 3.996.38 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/fetch-http-handler': 5.6.3 - '@smithy/node-http-handler': 4.9.3 - '@smithy/types': 4.15.1 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/s3-request-presigner@3.1079.0': + '@aws-sdk/nested-clients@3.997.23': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/signature-v4-multi-region': 3.996.35 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/fetch-http-handler': 5.5.2 + '@smithy/node-http-handler': 4.8.2 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws-sdk/s3-request-presigner@3.1075.0': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/signature-v4-multi-region': 3.996.38 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/signature-v4-multi-region': 3.996.35 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.996.38': + '@aws-sdk/signature-v4-multi-region@3.996.35': dependencies: - '@aws-sdk/types': 3.973.15 - '@smithy/signature-v4': 5.6.2 - '@smithy/types': 4.15.1 + '@aws-sdk/types': 3.973.13 + '@smithy/signature-v4': 5.5.2 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1079.0': + '@aws-sdk/token-providers@3.1074.0': dependencies: - '@aws-sdk/core': 3.974.27 - '@aws-sdk/nested-clients': 3.997.27 - '@aws-sdk/types': 3.973.15 - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@aws-sdk/core': 3.974.23 + '@aws-sdk/nested-clients': 3.997.23 + '@aws-sdk/types': 3.973.13 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/types@3.973.15': + '@aws-sdk/types@3.973.13': dependencies: - '@smithy/types': 4.15.1 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@aws-sdk/util-dynamodb@3.996.5(@aws-sdk/client-dynamodb@3.1079.0)': + '@aws-sdk/util-dynamodb@3.996.5(@aws-sdk/client-dynamodb@3.1075.0)': dependencies: - '@aws-sdk/client-dynamodb': 3.1079.0 + '@aws-sdk/client-dynamodb': 3.1075.0 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.33': + '@aws-sdk/util-locate-window@3.965.8': dependencies: - '@smithy/types': 4.15.1 tslib: 2.8.1 - '@aws/lambda-invoke-store@0.3.0': {} + '@aws-sdk/xml-builder@3.972.31': + dependencies: + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.2.4': {} '@biomejs/biome@1.9.4': optionalDependencies: @@ -2290,7 +2378,7 @@ snapshots: '@gcforms/database@1.1.2(typescript@5.9.3)': dependencies: - '@aws-sdk/client-secrets-manager': 3.1079.0 + '@aws-sdk/client-secrets-manager': 3.1075.0 '@prisma/adapter-pg': 7.8.0 '@prisma/client': 7.8.0(typescript@5.9.3) pg: 8.20.0 @@ -2324,7 +2412,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@oxc-project/types@0.138.0': {} + '@oxc-project/types@0.137.0': {} '@paralleldrive/cuid2@2.3.1': dependencies: @@ -2381,53 +2469,53 @@ snapshots: dependencies: '@redis/client': 1.6.1 - '@rolldown/binding-android-arm64@1.1.4': + '@rolldown/binding-android-arm64@1.1.3': optional: true - '@rolldown/binding-darwin-arm64@1.1.4': + '@rolldown/binding-darwin-arm64@1.1.3': optional: true - '@rolldown/binding-darwin-x64@1.1.4': + '@rolldown/binding-darwin-x64@1.1.3': optional: true - '@rolldown/binding-freebsd-x64@1.1.4': + '@rolldown/binding-freebsd-x64@1.1.3': optional: true - '@rolldown/binding-linux-arm-gnueabihf@1.1.4': + '@rolldown/binding-linux-arm-gnueabihf@1.1.3': optional: true - '@rolldown/binding-linux-arm64-gnu@1.1.4': + '@rolldown/binding-linux-arm64-gnu@1.1.3': optional: true - '@rolldown/binding-linux-arm64-musl@1.1.4': + '@rolldown/binding-linux-arm64-musl@1.1.3': optional: true - '@rolldown/binding-linux-ppc64-gnu@1.1.4': + '@rolldown/binding-linux-ppc64-gnu@1.1.3': optional: true - '@rolldown/binding-linux-s390x-gnu@1.1.4': + '@rolldown/binding-linux-s390x-gnu@1.1.3': optional: true - '@rolldown/binding-linux-x64-gnu@1.1.4': + '@rolldown/binding-linux-x64-gnu@1.1.3': optional: true - '@rolldown/binding-linux-x64-musl@1.1.4': + '@rolldown/binding-linux-x64-musl@1.1.3': optional: true - '@rolldown/binding-openharmony-arm64@1.1.4': + '@rolldown/binding-openharmony-arm64@1.1.3': optional: true - '@rolldown/binding-wasm32-wasi@1.1.4': + '@rolldown/binding-wasm32-wasi@1.1.3': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true - '@rolldown/binding-win32-arm64-msvc@1.1.4': + '@rolldown/binding-win32-arm64-msvc@1.1.3': optional: true - '@rolldown/binding-win32-x64-msvc@1.1.4': + '@rolldown/binding-win32-x64-msvc@1.1.3': optional: true '@rolldown/pluginutils@1.0.1': {} @@ -2453,37 +2541,52 @@ snapshots: '@sinonjs/commons': 3.0.1 type-detect: 4.1.0 - '@smithy/core@3.29.1': + '@smithy/core@3.26.0': dependencies: - '@smithy/types': 4.15.1 + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.4.6': + '@smithy/credential-provider-imds@4.4.2': dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.6.3': + '@smithy/fetch-http-handler@5.5.2': dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/node-http-handler@4.9.3': + '@smithy/is-array-buffer@2.2.0': dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 tslib: 2.8.1 - '@smithy/signature-v4@5.6.2': + '@smithy/node-http-handler@4.8.2': dependencies: - '@smithy/core': 3.29.1 - '@smithy/types': 4.15.1 + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 tslib: 2.8.1 - '@smithy/types@4.15.1': + '@smithy/signature-v4@5.5.2': dependencies: + '@smithy/core': 3.26.0 + '@smithy/types': 4.15.0 + tslib: 2.8.1 + + '@smithy/types@4.15.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 '@standard-schema/spec@1.1.0': {} @@ -2595,13 +2698,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.9(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0))': + '@vitest/mocker@4.1.9(vite@8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4))': dependencies: '@vitest/spy': 4.1.9 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0) + vite: 8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4) '@vitest/pretty-format@4.1.9': dependencies: @@ -2817,7 +2920,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@2.3.0: {} + es-module-lexer@2.1.0: {} es-object-atoms@1.1.2: dependencies: @@ -2930,9 +3033,9 @@ snapshots: dependencies: reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.5): + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: - picomatch: 4.0.5 + picomatch: 4.0.4 fill-range@7.1.1: dependencies: @@ -3017,8 +3120,6 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 - globrex@0.1.2: {} - gopd@1.2.0: {} got@14.6.6: @@ -3281,7 +3382,7 @@ snapshots: picomatch@2.3.2: {} - picomatch@4.0.5: {} + picomatch@4.0.4: {} pino-abstract-transport@2.0.0: dependencies: @@ -3324,7 +3425,7 @@ snapshots: dependencies: queue-lit: 1.5.2 - postcss@8.5.16: + postcss@8.5.15: dependencies: nanoid: 3.3.15 picocolors: 1.1.1 @@ -3413,26 +3514,26 @@ snapshots: reusify@1.1.0: {} - rolldown@1.1.4: + rolldown@1.1.3: dependencies: - '@oxc-project/types': 0.138.0 + '@oxc-project/types': 0.137.0 '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rolldown/binding-android-arm64': 1.1.4 - '@rolldown/binding-darwin-arm64': 1.1.4 - '@rolldown/binding-darwin-x64': 1.1.4 - '@rolldown/binding-freebsd-x64': 1.1.4 - '@rolldown/binding-linux-arm-gnueabihf': 1.1.4 - '@rolldown/binding-linux-arm64-gnu': 1.1.4 - '@rolldown/binding-linux-arm64-musl': 1.1.4 - '@rolldown/binding-linux-ppc64-gnu': 1.1.4 - '@rolldown/binding-linux-s390x-gnu': 1.1.4 - '@rolldown/binding-linux-x64-gnu': 1.1.4 - '@rolldown/binding-linux-x64-musl': 1.1.4 - '@rolldown/binding-openharmony-arm64': 1.1.4 - '@rolldown/binding-wasm32-wasi': 1.1.4 - '@rolldown/binding-win32-arm64-msvc': 1.1.4 - '@rolldown/binding-win32-x64-msvc': 1.1.4 + '@rolldown/binding-android-arm64': 1.1.3 + '@rolldown/binding-darwin-arm64': 1.1.3 + '@rolldown/binding-darwin-x64': 1.1.3 + '@rolldown/binding-freebsd-x64': 1.1.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.1.3 + '@rolldown/binding-linux-arm64-gnu': 1.1.3 + '@rolldown/binding-linux-arm64-musl': 1.1.3 + '@rolldown/binding-linux-ppc64-gnu': 1.1.3 + '@rolldown/binding-linux-s390x-gnu': 1.1.3 + '@rolldown/binding-linux-x64-gnu': 1.1.3 + '@rolldown/binding-linux-x64-musl': 1.1.3 + '@rolldown/binding-openharmony-arm64': 1.1.3 + '@rolldown/binding-wasm32-wasi': 1.1.3 + '@rolldown/binding-win32-arm64-msvc': 1.1.3 + '@rolldown/binding-win32-x64-msvc': 1.1.3 run-parallel@1.2.0: dependencies: @@ -3572,8 +3673,8 @@ snapshots: tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 tinyrainbow@3.1.0: {} @@ -3587,7 +3688,7 @@ snapshots: optionalDependencies: typescript: 5.9.3 - tsc-alias@1.9.0: + tsc-alias@1.8.17: dependencies: chokidar: 3.6.0 commander: 9.5.0 @@ -3597,13 +3698,9 @@ snapshots: normalize-path: 3.0.0 plimit-lit: 1.6.1 - tsconfck@3.1.6(typescript@5.9.3): - optionalDependencies: - typescript: 5.9.3 - tslib@2.8.1: {} - tsx@4.23.0: + tsx@4.22.4: dependencies: esbuild: 0.28.1 optionalDependencies: @@ -3632,61 +3729,50 @@ snapshots: vary@1.1.2: {} - vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)): - dependencies: - debug: 4.4.3 - globrex: 0.1.2 - tsconfck: 3.1.6(typescript@5.9.3) - optionalDependencies: - vite: 8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0) - transitivePeerDependencies: - - supports-color - - typescript - - vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0): + vite@8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4): dependencies: lightningcss: 1.32.0 - picomatch: 4.0.5 - postcss: 8.5.16 - rolldown: 1.1.4 + picomatch: 4.0.4 + postcss: 8.5.15 + rolldown: 1.1.3 tinyglobby: 0.2.17 optionalDependencies: '@types/node': 22.20.0 esbuild: 0.28.1 fsevents: 2.3.3 - tsx: 4.23.0 + tsx: 4.22.4 vitest-mock-express@2.2.0: dependencies: '@types/express': 4.17.25 - vitest-mock-extended@4.0.0(typescript@5.9.3)(vitest@4.1.9(@types/node@22.20.0)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0))): + vitest-mock-extended@4.0.0(typescript@5.9.3)(vitest@4.1.9(@types/node@22.20.0)(vite@8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4))): dependencies: ts-essentials: 10.2.1(typescript@5.9.3) typescript: 5.9.3 - vitest: 4.1.9(@types/node@22.20.0)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)) + vitest: 4.1.9(@types/node@22.20.0)(vite@8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4)) - vitest@4.1.9(@types/node@22.20.0)(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)): + vitest@4.1.9(@types/node@22.20.0)(vite@8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4)): dependencies: '@vitest/expect': 4.1.9 - '@vitest/mocker': 4.1.9(vite@8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0)) + '@vitest/mocker': 4.1.9(vite@8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4)) '@vitest/pretty-format': 4.1.9 '@vitest/runner': 4.1.9 '@vitest/snapshot': 4.1.9 '@vitest/spy': 4.1.9 '@vitest/utils': 4.1.9 - es-module-lexer: 2.3.0 + es-module-lexer: 2.1.0 expect-type: 1.4.0 magic-string: 0.30.21 obug: 2.1.3 pathe: 2.0.3 - picomatch: 4.0.5 + picomatch: 4.0.4 std-env: 4.1.0 tinybench: 2.9.0 tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 8.1.3(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.23.0) + vite: 8.1.0(@types/node@22.20.0)(esbuild@0.28.1)(tsx@4.22.4) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.20.0 diff --git a/vitest.config.mts b/vitest.config.mts index a8986e00..5426510e 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -1,9 +1,10 @@ -import tsconfigPaths from "vite-tsconfig-paths"; import { defineConfig } from "vitest/config"; // biome-ignore lint/style/noDefaultExport: export default defineConfig({ - plugins: [tsconfigPaths()], + resolve: { + tsconfigPaths: true, + }, test: { include: ["test/**/*.test.ts"], setupFiles: "vitest-setup.ts", From d755cc07472982e0f9ec17d8b37740cda3a061c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Wed, 24 Jun 2026 14:21:27 -0400 Subject: [PATCH 5/9] chore: fix broken unit tests --- test/lib/encryption/encryptResponse.test.ts | 6 ++--- test/lib/formsClient/getFormTemplate.test.ts | 22 +++++++++++-------- test/lib/formsClient/getPublicKey.test.ts | 2 +- test/lib/idp/verifyAccessToken.test.ts | 2 +- test/lib/integration/zitadelConnector.test.ts | 6 ++--- .../storage/requestContextualStore.test.ts | 8 +++---- ...ySupportAboutFormSubmissionProblem.test.ts | 2 +- test/lib/vault/confirmFormSubmission.test.ts | 2 +- test/lib/vault/getFormSubmission.test.ts | 2 +- ...rmSubmissionAttachmentDownloadLink.test.ts | 2 +- test/lib/vault/getNewFormSubmissions.test.ts | 18 ++++++++++++++- .../mappers/formSubmission.mapper.test.ts | 18 ++++++++++----- .../reportProblemWithFormSubmission.test.ts | 2 +- test/operations/retrieveTemplate.v1.test.ts | 2 +- 14 files changed, 61 insertions(+), 33 deletions(-) diff --git a/test/lib/encryption/encryptResponse.test.ts b/test/lib/encryption/encryptResponse.test.ts index 788356c9..e5abe58e 100644 --- a/test/lib/encryption/encryptResponse.test.ts +++ b/test/lib/encryption/encryptResponse.test.ts @@ -32,9 +32,9 @@ describe("encryptFormSubmission should", () => { }); const logMessageSpy = vi.spyOn(logMessage, "error"); - expect(() => - encryptResponse("serviceAccountPublicKey", "payload"), - ).toThrowError("custom error"); + expect(() => encryptResponse("serviceAccountPublicKey", "payload")).toThrow( + "custom error", + ); expect(logMessageSpy).toHaveBeenCalledWith( customError, diff --git a/test/lib/formsClient/getFormTemplate.test.ts b/test/lib/formsClient/getFormTemplate.test.ts index 8cda5179..490c839e 100644 --- a/test/lib/formsClient/getFormTemplate.test.ts +++ b/test/lib/formsClient/getFormTemplate.test.ts @@ -1,4 +1,8 @@ -import { type PrismaClient, type Template, prisma } from "@gcforms/database"; +import { + type PrismaClient, + type TemplateVersion, + prisma, +} from "@gcforms/database"; import { getFormTemplate } from "@lib/formsClient/getFormTemplate.js"; import { logMessage } from "@lib/logging/logger.js"; import { beforeEach, describe, expect, it, vi } from "vitest"; @@ -13,15 +17,15 @@ describe("getFormTemplate should", () => { }); it("return an undefined form template if database was not able to find it", async () => { - prismaMock.template.findUnique.mockResolvedValueOnce(null); + prismaMock.templateVersion.findUnique.mockResolvedValueOnce(null); - const formTemplate = await getFormTemplate("clzamy5qv0000115huc4bh90m"); + const formTemplate = await getFormTemplate("clzamy5qv0000115huc4bh90m", 1); expect(formTemplate).toBeUndefined(); }); it("return a form template if database was able to find it", async () => { - prismaMock.template.findUnique.mockResolvedValue({ + prismaMock.templateVersion.findUnique.mockResolvedValue({ jsonConfig: { elements: [ { @@ -30,9 +34,9 @@ describe("getFormTemplate should", () => { }, ], }, - } as unknown as Template); + } as unknown as TemplateVersion); - const formTemplate = await getFormTemplate("clzamy5qv0000115huc4bh90m"); + const formTemplate = await getFormTemplate("clzamy5qv0000115huc4bh90m", 1); expect(formTemplate).toEqual({ jsonConfig: { @@ -48,12 +52,12 @@ describe("getFormTemplate should", () => { it("throw an error if database has an internal failure", async () => { const customError = new Error("custom error"); - prismaMock.template.findUnique.mockRejectedValueOnce(customError); + prismaMock.templateVersion.findUnique.mockRejectedValueOnce(customError); const logMessageSpy = vi.spyOn(logMessage, "error"); await expect(() => - getFormTemplate("clzamy5qv0000115huc4bh90m"), - ).rejects.toThrowError(customError); + getFormTemplate("clzamy5qv0000115huc4bh90m", 1), + ).rejects.toThrow(customError); expect(logMessageSpy).toHaveBeenCalledWith( customError, diff --git a/test/lib/formsClient/getPublicKey.test.ts b/test/lib/formsClient/getPublicKey.test.ts index c4e6a2da..f598ee92 100644 --- a/test/lib/formsClient/getPublicKey.test.ts +++ b/test/lib/formsClient/getPublicKey.test.ts @@ -56,7 +56,7 @@ describe("getPublicKey should", () => { prismaMock.apiServiceAccount.findUnique.mockRejectedValueOnce(customError); const logMessageSpy = vi.spyOn(logMessage, "info"); - await expect(() => getPublicKey("254354365464565461")).rejects.toThrowError( + await expect(() => getPublicKey("254354365464565461")).rejects.toThrow( customError, ); diff --git a/test/lib/idp/verifyAccessToken.test.ts b/test/lib/idp/verifyAccessToken.test.ts index 52939620..f473d79a 100644 --- a/test/lib/idp/verifyAccessToken.test.ts +++ b/test/lib/idp/verifyAccessToken.test.ts @@ -201,7 +201,7 @@ describe("verifyAccessToken should", () => { "RkS8hzu0MtwL+Qs2lK7KX9CLK7v6lxYpqs7ns5MwuOs=", "0000", ), - ).rejects.toThrowError(ZitadelConnectionError); + ).rejects.toThrow(ZitadelConnectionError); expect(logMessageSpy).toHaveBeenCalledWith( connectionError, diff --git a/test/lib/integration/zitadelConnector.test.ts b/test/lib/integration/zitadelConnector.test.ts index 510a722b..ac5ee2e8 100644 --- a/test/lib/integration/zitadelConnector.test.ts +++ b/test/lib/integration/zitadelConnector.test.ts @@ -43,9 +43,9 @@ describe("introspectAccessToken should", () => { const logMessageSpy = vi.spyOn(logMessage, "info"); - await expect(() => - introspectAccessToken("accessToken"), - ).rejects.toThrowError(ZitadelConnectionError); + await expect(() => introspectAccessToken("accessToken")).rejects.toThrow( + ZitadelConnectionError, + ); expect(logMessageSpy).toHaveBeenCalledWith( connectionError, diff --git a/test/lib/storage/requestContextualStore.test.ts b/test/lib/storage/requestContextualStore.test.ts index 528f51b6..ec1c8217 100644 --- a/test/lib/storage/requestContextualStore.test.ts +++ b/test/lib/storage/requestContextualStore.test.ts @@ -22,7 +22,7 @@ describe("requestContextualStore", () => { it("throw an error if the requestContextualStore is undefined", () => { expect(() => saveRequestContextData(RequestContextualStoreKey.serviceUserId, "test"), - ).toThrowError("requestContextualStore is undefined"); + ).toThrow("requestContextualStore is undefined"); }); }); @@ -40,7 +40,7 @@ describe("requestContextualStore", () => { it("throw an error if the requestContextualStore is undefined", () => { expect(() => retrieveOptionalRequestContextData(RequestContextualStoreKey.clientIp), - ).toThrowError("requestContextualStore is undefined"); + ).toThrow("requestContextualStore is undefined"); }); }); @@ -61,7 +61,7 @@ describe("requestContextualStore", () => { expect(() => retrieveRequestContextData(RequestContextualStoreKey.clientIp), - ).toThrowError( + ).toThrow( "requestContextualStore does not have any set value for key: clientIp", ); }); @@ -70,7 +70,7 @@ describe("requestContextualStore", () => { it("throw an error if the requestContextualStore is undefined", () => { expect(() => retrieveRequestContextData(RequestContextualStoreKey.clientIp), - ).toThrowError("requestContextualStore is undefined"); + ).toThrow("requestContextualStore is undefined"); }); }); }); diff --git a/test/lib/support/notifySupportAboutFormSubmissionProblem.test.ts b/test/lib/support/notifySupportAboutFormSubmissionProblem.test.ts index cc67b816..c9511378 100644 --- a/test/lib/support/notifySupportAboutFormSubmissionProblem.test.ts +++ b/test/lib/support/notifySupportAboutFormSubmissionProblem.test.ts @@ -67,7 +67,7 @@ Here is my problem
"en", EnvironmentMode.production, ), - ).rejects.toThrowError(customError); + ).rejects.toThrow(customError); expect(logMessageSpy).toHaveBeenCalledWith( customError, diff --git a/test/lib/vault/confirmFormSubmission.test.ts b/test/lib/vault/confirmFormSubmission.test.ts index 0084a81a..e51af1f3 100644 --- a/test/lib/vault/confirmFormSubmission.test.ts +++ b/test/lib/vault/confirmFormSubmission.test.ts @@ -118,7 +118,7 @@ describe("confirmFormSubmission should", () => { "01-08-a571", "620b203c-9836-4000-bf30-1c3bcc26b834", ), - ).rejects.toThrowError(customError); + ).rejects.toThrow(customError); expect(logMessageSpy).toHaveBeenCalledWith( customError, diff --git a/test/lib/vault/getFormSubmission.test.ts b/test/lib/vault/getFormSubmission.test.ts index e96fb3c3..14c4e067 100644 --- a/test/lib/vault/getFormSubmission.test.ts +++ b/test/lib/vault/getFormSubmission.test.ts @@ -48,7 +48,7 @@ describe("getFormSubmission should", () => { await expect(() => getFormSubmission("clzamy5qv0000115huc4bh90m", "01-08-a571"), - ).rejects.toThrowError(customError); + ).rejects.toThrow(customError); expect(logMessageSpy).toHaveBeenCalledWith( customError, diff --git a/test/lib/vault/getFormSubmissionAttachmentDownloadLink.test.ts b/test/lib/vault/getFormSubmissionAttachmentDownloadLink.test.ts index c4eba081..126fd6b8 100644 --- a/test/lib/vault/getFormSubmissionAttachmentDownloadLink.test.ts +++ b/test/lib/vault/getFormSubmissionAttachmentDownloadLink.test.ts @@ -33,7 +33,7 @@ describe("getFormSubmissionAttachmentDownloadLink should", () => { getFormSubmissionAttachmentDownloadLink( "form_attachments/2025-06-09/0c7c3414-05e2-4ae6-a825-683857e4c0c4/image.jpeg", ), - ).rejects.toThrowError(customError); + ).rejects.toThrow(customError); expect(logMessageSpy).toHaveBeenCalledWith( customError, diff --git a/test/lib/vault/getNewFormSubmissions.test.ts b/test/lib/vault/getNewFormSubmissions.test.ts index 518c601b..8b9cdb8e 100644 --- a/test/lib/vault/getNewFormSubmissions.test.ts +++ b/test/lib/vault/getNewFormSubmissions.test.ts @@ -30,10 +30,12 @@ describe("getNewFormSubmissions should", () => { { Name: "ABC", CreatedAt: 123, + Version: 8, }, { Name: "DEF", CreatedAt: 123, + Version: 8, }, ], }); @@ -54,11 +56,13 @@ describe("getNewFormSubmissions should", () => { { Name: "ABC", CreatedAt: 123, + Version: 8, }, ], LastEvaluatedKey: { Name: "ABC", CreatedAt: 123, + Version: 8, }, }) .resolvesOnce({ @@ -66,10 +70,12 @@ describe("getNewFormSubmissions should", () => { { Name: "DEF", CreatedAt: 123, + Version: 8, }, { Name: "GHI", CreatedAt: 123, + Version: 8, }, ], }); @@ -83,6 +89,7 @@ describe("getNewFormSubmissions should", () => { { createdAt: 123, name: "ABC", + version: 8, }, ]); }); @@ -95,15 +102,18 @@ describe("getNewFormSubmissions should", () => { { Name: "ABC", CreatedAt: 123, + Version: 8, }, { Name: "DEF", CreatedAt: 123, + Version: 8, }, ], LastEvaluatedKey: { Name: "DEF", CreatedAt: 123, + Version: 8, }, }) .resolvesOnce({ @@ -111,10 +121,12 @@ describe("getNewFormSubmissions should", () => { { Name: "GHI", CreatedAt: 123, + Version: 8, }, { Name: "JKL", CreatedAt: 123, + Version: 8, }, ], }); @@ -128,18 +140,22 @@ describe("getNewFormSubmissions should", () => { { createdAt: 123, name: "ABC", + version: 8, }, { createdAt: 123, name: "DEF", + version: 8, }, { createdAt: 123, name: "GHI", + version: 8, }, { createdAt: 123, name: "JKL", + version: 8, }, ]); }); @@ -151,7 +167,7 @@ describe("getNewFormSubmissions should", () => { await expect( getNewFormSubmissions("clzamy5qv0000115huc4bh90m", 100), - ).rejects.toThrowError(customError); + ).rejects.toThrow(customError); expect(logMessageSpy).toHaveBeenCalledWith( customError, diff --git a/test/lib/vault/mappers/formSubmission.mapper.test.ts b/test/lib/vault/mappers/formSubmission.mapper.test.ts index 6061eb94..592bdf20 100644 --- a/test/lib/vault/mappers/formSubmission.mapper.test.ts +++ b/test/lib/vault/mappers/formSubmission.mapper.test.ts @@ -11,11 +11,13 @@ describe("in formSubmission mapper", () => { const newFormSubmission = mapNewFormSubmissionFromDynamoDbResponse({ Name: "18-06-977e7", CreatedAt: 1750263415913, + Version: 8, }); expect(newFormSubmission).toEqual({ name: "18-06-977e7", createdAt: 1750263415913, + version: 8, }); }); @@ -24,7 +26,7 @@ describe("in formSubmission mapper", () => { mapNewFormSubmissionFromDynamoDbResponse({ Name: "18-06-977e7", }), - ).toThrowError("Missing key properties in DynamoDB response"); + ).toThrow("Missing key properties in DynamoDB response"); }); it("throw an error when DynamoDB response is invalid", () => { @@ -33,7 +35,7 @@ describe("in formSubmission mapper", () => { Name: "18-06-977e7", CreatedAt: "1750263415913", }), - ).toThrowError("Unexpected type in DynamoDB response"); + ).toThrow("Unexpected type in DynamoDB response"); }); }); @@ -53,6 +55,7 @@ describe("in formSubmission mapper", () => { scanStatus: "NO_THREATS_FOUND", }, ]), + Version: 8, }); expect(formSubmission).toEqual({ @@ -69,6 +72,7 @@ describe("in formSubmission mapper", () => { scanStatus: AttachmentScanStatus.noThreatsFound, }, ], + version: 8, }); }); @@ -88,6 +92,7 @@ describe("in formSubmission mapper", () => { scanStatus: "NO_THREATS_FOUND", }, ]), + Version: 8, }); expect(formSubmission).toEqual({ @@ -105,6 +110,7 @@ describe("in formSubmission mapper", () => { md5: undefined, }, ], + version: 8, }); }); @@ -115,6 +121,7 @@ describe("in formSubmission mapper", () => { ConfirmationCode: "99063d75-9804-4efa-8f4c-605b4ba6ad95", FormSubmission: '{"1":"Test response"}', FormSubmissionHash: "5981e9cd2a2f0032e9b8c99eb7bb8841", + Version: 8, }); expect(formSubmission).toEqual({ @@ -124,6 +131,7 @@ describe("in formSubmission mapper", () => { answers: '{"1":"Test response"}', checksum: "5981e9cd2a2f0032e9b8c99eb7bb8841", attachments: [], + version: 8, }); }); @@ -137,7 +145,7 @@ describe("in formSubmission mapper", () => { FormSubmissionHash: "5981e9cd2a2f0032e9b8c99eb7bb8841", SubmissionAttachments: [], }), - ).toThrowError("Unexpected type in DynamoDB response"); + ).toThrow("Unexpected type in DynamoDB response"); }); it("throw an error when DynamoDB response is incomplete", () => { @@ -148,7 +156,7 @@ describe("in formSubmission mapper", () => { ConfirmationCode: "99063d75-9804-4efa-8f4c-605b4ba6ad95", FormSubmissionHash: "5981e9cd2a2f0032e9b8c99eb7bb8841", }), - ).toThrowError("Missing key properties in DynamoDB response"); + ).toThrow("Missing key properties in DynamoDB response"); }); it("throw an error when DynamoDB response is invalid", () => { @@ -160,7 +168,7 @@ describe("in formSubmission mapper", () => { FormSubmission: '{"1":"Test response"}', FormSubmissionHash: "5981e9cd2a2f0032e9b8c99eb7bb8841", }), - ).toThrowError("Unexpected type in DynamoDB response"); + ).toThrow("Unexpected type in DynamoDB response"); }); }); }); diff --git a/test/lib/vault/reportProblemWithFormSubmission.test.ts b/test/lib/vault/reportProblemWithFormSubmission.test.ts index 669f50fe..0f8a9156 100644 --- a/test/lib/vault/reportProblemWithFormSubmission.test.ts +++ b/test/lib/vault/reportProblemWithFormSubmission.test.ts @@ -95,7 +95,7 @@ describe("reportProblemWithFormSubmission should", () => { "clzamy5qv0000115huc4bh90m", "01-08-a571", ), - ).rejects.toThrowError(customError); + ).rejects.toThrow(customError); expect(logMessageSpy).toHaveBeenCalledWith( customError, diff --git a/test/operations/retrieveTemplate.v1.test.ts b/test/operations/retrieveTemplate.v1.test.ts index c1b13bcb..e4723947 100644 --- a/test/operations/retrieveTemplate.v1.test.ts +++ b/test/operations/retrieveTemplate.v1.test.ts @@ -90,7 +90,7 @@ describe("retrieveTemplateOperation handler should", () => { expect(nextMock).toHaveBeenCalledWith( new Error( - "[operation] Internal error while retrieving template. Params: formId = clzsn6tao000611j50dexeob0", + "[operation] Internal error while retrieving template. Params: formId = clzsn6tao000611j50dexeob0 ; version = undefined", ), ); }); From 463423b85aa941a68671dd86f6be679f06c610fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Thu, 25 Jun 2026 08:38:37 -0400 Subject: [PATCH 6/9] chore: change file extension for vitest config file and also remove unnecessary logs when running tests --- vitest.config.mts => vitest.config.ts | 1 + 1 file changed, 1 insertion(+) rename vitest.config.mts => vitest.config.ts (90%) diff --git a/vitest.config.mts b/vitest.config.ts similarity index 90% rename from vitest.config.mts rename to vitest.config.ts index 5426510e..f94ce412 100644 --- a/vitest.config.mts +++ b/vitest.config.ts @@ -6,6 +6,7 @@ export default defineConfig({ tsconfigPaths: true, }, test: { + silent: "passed-only", include: ["test/**/*.test.ts"], setupFiles: "vitest-setup.ts", }, From 15233a130b5d5fdeeaa31fe236eabf6e8b4550a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Thu, 25 Jun 2026 09:54:52 -0400 Subject: [PATCH 7/9] chore: enable some security mechanisms in PNPM --- pnpm-workspace.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 97db6de7..4af66930 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,6 @@ +blockExoticSubdeps: true +minimumReleaseAge: 10080 # 7 days + allowBuilds: '@biomejs/biome': false esbuild: false From cae835429d15aa9484fd44b88feb0763c6ab038d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Thu, 25 Jun 2026 09:55:23 -0400 Subject: [PATCH 8/9] chore: add more unit tests --- test/lib/formsClient/getFormTemplate.test.ts | 30 ++++++++ .../mappers/formSubmission.mapper.test.ts | 31 ++++++++ test/mocks/dynamodb.ts | 1 + .../retrieveNewSubmissions.v1.test.ts | 2 + test/operations/retrieveSubmission.v1.test.ts | 8 +++ test/operations/retrieveTemplate.v1.test.ts | 70 +++++++++++++++++-- 6 files changed, 135 insertions(+), 7 deletions(-) diff --git a/test/lib/formsClient/getFormTemplate.test.ts b/test/lib/formsClient/getFormTemplate.test.ts index 490c839e..8606b8cf 100644 --- a/test/lib/formsClient/getFormTemplate.test.ts +++ b/test/lib/formsClient/getFormTemplate.test.ts @@ -1,5 +1,6 @@ import { type PrismaClient, + type Template, type TemplateVersion, prisma, } from "@gcforms/database"; @@ -50,6 +51,35 @@ describe("getFormTemplate should", () => { }); }); + // This test can be deleted once form versioning is implemented in Production and migrated old form template database entries to the new versioned schema + it("return a form template even if form versioning is not fully deployed (testing fallback Prisma query)", async () => { + prismaMock.templateVersion.findUnique.mockResolvedValue(null); + + prismaMock.template.findUnique.mockResolvedValue({ + jsonConfig: { + elements: [ + { + id: 1, + type: "textField", + }, + ], + }, + } as unknown as Template); + + const formTemplate = await getFormTemplate("clzamy5qv0000115huc4bh90m", 1); + + expect(formTemplate).toEqual({ + jsonConfig: { + elements: [ + { + id: 1, + type: "textField", + }, + ], + }, + }); + }); + it("throw an error if database has an internal failure", async () => { const customError = new Error("custom error"); prismaMock.templateVersion.findUnique.mockRejectedValueOnce(customError); diff --git a/test/lib/vault/mappers/formSubmission.mapper.test.ts b/test/lib/vault/mappers/formSubmission.mapper.test.ts index 592bdf20..65447827 100644 --- a/test/lib/vault/mappers/formSubmission.mapper.test.ts +++ b/test/lib/vault/mappers/formSubmission.mapper.test.ts @@ -21,6 +21,20 @@ describe("in formSubmission mapper", () => { }); }); + // This test can be deleted once form versioning is well established in Production + it("return proper NewFormSubmission when DynamoDB response does not include a Version attribute (testing backward compatibility with submissions that were produced when form versioning did not exist)", () => { + const newFormSubmission = mapNewFormSubmissionFromDynamoDbResponse({ + Name: "18-06-977e7", + CreatedAt: 1750263415913, + }); + + expect(newFormSubmission).toEqual( + expect.objectContaining({ + version: 1, + }), + ); + }); + it("throw an error when DynamoDB response is incomplete", () => { expect(() => mapNewFormSubmissionFromDynamoDbResponse({ @@ -135,6 +149,23 @@ describe("in formSubmission mapper", () => { }); }); + // This test can be deleted once form versioning is well established in Production + it("return proper FormSubmission when DynamoDB response does not include a Version attribute (testing backward compatibility with submissions that were produced when form versioning did not exist)", () => { + const formSubmission = mapFormSubmissionFromDynamoDbResponse({ + CreatedAt: 1750263415913, + "Status#CreatedAt": "New#1750263415913", + ConfirmationCode: "99063d75-9804-4efa-8f4c-605b4ba6ad95", + FormSubmission: '{"1":"Test response"}', + FormSubmissionHash: "5981e9cd2a2f0032e9b8c99eb7bb8841", + }); + + expect(formSubmission).toEqual( + expect.objectContaining({ + version: 1, + }), + ); + }); + it("throw an error when SubmissionAttachments in DynamoDB response is present but invalid", () => { expect(() => mapFormSubmissionFromDynamoDbResponse({ diff --git a/test/mocks/dynamodb.ts b/test/mocks/dynamodb.ts index 8b51c463..238d522c 100644 --- a/test/mocks/dynamodb.ts +++ b/test/mocks/dynamodb.ts @@ -10,5 +10,6 @@ export function buildMockedVaultItem( ConfirmationCode: confirmationCode, FormSubmission: '{"1":"Test response"}', FormSubmissionHash: "5981e9cd2a2f0032e9b8c99eb7bb8841", + Version: 8, }; } diff --git a/test/operations/retrieveNewSubmissions.v1.test.ts b/test/operations/retrieveNewSubmissions.v1.test.ts index 39ca119d..5b979814 100644 --- a/test/operations/retrieveNewSubmissions.v1.test.ts +++ b/test/operations/retrieveNewSubmissions.v1.test.ts @@ -53,6 +53,7 @@ describe("retrieveNewSubmissionsOperation handler should", () => { { name: "ABC", createdAt: 123, + version: 8, }, ]); @@ -66,6 +67,7 @@ describe("retrieveNewSubmissionsOperation handler should", () => { { createdAt: 123, name: "ABC", + version: 8, }, ]); expect(auditLogSpy).toHaveBeenNthCalledWith(1, { diff --git a/test/operations/retrieveSubmission.v1.test.ts b/test/operations/retrieveSubmission.v1.test.ts index 08c0634a..b0558ba6 100644 --- a/test/operations/retrieveSubmission.v1.test.ts +++ b/test/operations/retrieveSubmission.v1.test.ts @@ -60,6 +60,7 @@ describe("retrieveSubmissionOperation handler should", () => { answers: "", checksum: "", attachments: [], + version: 8, }); getPublicKeyMock.mockResolvedValueOnce("publicKey"); encryptResponseMock.mockReturnValueOnce({ @@ -91,6 +92,7 @@ describe("retrieveSubmissionOperation handler should", () => { confirmationCode: "", answers: "", checksum: "", + version: 8, }), ); @@ -117,6 +119,7 @@ describe("retrieveSubmissionOperation handler should", () => { scanStatus: AttachmentScanStatus.noThreatsFound, }, ], + version: 8, }); getFormSubmissionAttachmentDownloadLinkMock.mockResolvedValueOnce( "https://download-link", @@ -160,6 +163,7 @@ describe("retrieveSubmissionOperation handler should", () => { isPotentiallyMalicious: false, }, ], + version: 8, }), ); @@ -224,6 +228,7 @@ describe("retrieveSubmissionOperation handler should", () => { scanStatus: attachmentScanStatus, }, ], + version: 8, }); getFormSubmissionAttachmentDownloadLinkMock.mockResolvedValueOnce( "https://download-link", @@ -253,6 +258,7 @@ describe("retrieveSubmissionOperation handler should", () => { isPotentiallyMalicious, }, ], + version: 8, }), ); }, @@ -274,6 +280,7 @@ describe("retrieveSubmissionOperation handler should", () => { scanStatus: AttachmentScanStatus.noThreatsFound, }, ], + version: 8, }); getFormSubmissionAttachmentDownloadLinkMock.mockRejectedValueOnce( new Error("custom error"), @@ -300,6 +307,7 @@ describe("retrieveSubmissionOperation handler should", () => { answers: "", checksum: "", attachments: [], + version: 8, }); getPublicKeyMock.mockImplementationOnce(() => { throw new Error("custom error"); diff --git a/test/operations/retrieveTemplate.v1.test.ts b/test/operations/retrieveTemplate.v1.test.ts index e4723947..28c975cb 100644 --- a/test/operations/retrieveTemplate.v1.test.ts +++ b/test/operations/retrieveTemplate.v1.test.ts @@ -17,21 +17,56 @@ vi.mocked(retrieveRequestContextData).mockReturnValue( ); describe("retrieveTemplateOperation handler should", () => { - const requestMock = getMockReq({ - params: { - formId: "clzsn6tao000611j50dexeob0", - }, - serviceUserId: "clzsn6tao000611j50dexeob0", - }); + let requestMock = getMockReq(); const { res: responseMock, next: nextMock, clearMockRes } = getMockRes(); beforeEach(() => { vi.clearAllMocks(); clearMockRes(); + + requestMock = getMockReq({ + params: { + formId: "clzsn6tao000611j50dexeob0", + }, + serviceUserId: "clzsn6tao000611j50dexeob0", + }); + }); + + it("respond with success when form template does exist", async () => { + getFormTemplateMock.mockResolvedValueOnce({ + jsonConfig: { + elements: [ + { + id: 1, + type: "textField", + }, + ], + }, + }); + + await retrieveTemplateOperationV1.handler( + requestMock, + responseMock, + nextMock, + ); + + expect(responseMock.json).toHaveBeenCalledWith({ + elements: [ + { + id: 1, + type: "textField", + }, + ], + }); + expect(auditLogSpy).toHaveBeenNthCalledWith(1, { + userId: "clzsn6tao000611j50dexeob0", + subject: { type: "Form", id: "clzsn6tao000611j50dexeob0" }, + event: "RetrieveTemplate", + }); }); - it("respond with success when form submission does exist", async () => { + it("respond with success when specific version of a form template does exist", async () => { getFormTemplateMock.mockResolvedValueOnce({ jsonConfig: { elements: [ @@ -42,6 +77,9 @@ describe("retrieveTemplateOperation handler should", () => { ], }, }); + requestMock.query = { + version: "8", + }; await retrieveTemplateOperationV1.handler( requestMock, @@ -79,6 +117,24 @@ describe("retrieveTemplateOperation handler should", () => { }); }); + it("respond with error when 'version' query parameter is not a number", async () => { + getFormTemplateMock.mockRejectedValueOnce(new Error("custom error")); + requestMock.query = { + version: "hello", + }; + + await retrieveTemplateOperationV1.handler( + requestMock, + responseMock, + nextMock, + ); + + expect(responseMock.status).toHaveBeenCalledWith(400); + expect(responseMock.json).toHaveBeenCalledWith({ + error: "URL parameter 'version' should be a number", + }); + }); + it("pass error to next function when processing fails due to internal error", async () => { getFormTemplateMock.mockRejectedValueOnce(new Error("custom error")); From eaefbe7fd7b54b04d96e9b60ea3257429664f26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Janin?= Date: Mon, 29 Jun 2026 08:31:03 -0400 Subject: [PATCH 9/9] chore: add esbuild and form-data dependencies to force use specific versions that are not flagged as vulnerable --- package.json | 5 ++++- pnpm-lock.yaml | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 3728145a..de3ad954 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,10 @@ "vite": "^8.0.16", "vitest": "^4.0.0", "vitest-mock-express": "^2.2.0", - "vitest-mock-extended": "^4.0.0" + "vitest-mock-extended": "^4.0.0", + "esbuild": "^0.28.1", + "form-data": "^4.0.6" }, + "//": "esbuild and form-data are not direct dependencies of forms-api; however, we had to add them to enforce the use of versions that are not flagged as vulnerable by our security scanning system (we should be able to remove them in the future)", "packageManager": "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4baa6b22..b84b6898 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -75,6 +75,12 @@ importers: aws-sdk-client-mock: specifier: ^4.0.2 version: 4.1.0 + esbuild: + specifier: ^0.28.1 + version: 0.28.1 + form-data: + specifier: ^4.0.6 + version: 4.0.6 pino-pretty: specifier: ^11.2.2 version: 11.3.0