diff --git a/.github/workflows/stage-2-test.yaml b/.github/workflows/stage-2-test.yaml index 04ed703ad..93ea26977 100644 --- a/.github/workflows/stage-2-test.yaml +++ b/.github/workflows/stage-2-test.yaml @@ -57,7 +57,7 @@ jobs: npm ci - name: "Generate dependencies" run: | - npm run generate-dependencies --workspaces --if-present + npm run generate-dependencies git diff --exit-code test-unit: name: "Unit tests" @@ -71,7 +71,7 @@ jobs: npm ci - name: "Generate dependencies" run: | - npm run generate-dependencies --workspaces --if-present + npm run generate-dependencies - name: "Run unit test suite" run: | make test-unit @@ -104,7 +104,7 @@ jobs: npm ci - name: "Generate dependencies" run: | - npm run generate-dependencies --workspaces --if-present + npm run generate-dependencies - name: "Run linting" run: | make test-lint @@ -120,7 +120,7 @@ jobs: npm ci - name: "Generate dependencies" run: | - npm run generate-dependencies --workspaces --if-present + npm run generate-dependencies - name: "Run typecheck" run: | make test-typecheck diff --git a/.github/workflows/stage-3-build.yaml b/.github/workflows/stage-3-build.yaml index 1b77536af..bc28487c1 100644 --- a/.github/workflows/stage-3-build.yaml +++ b/.github/workflows/stage-3-build.yaml @@ -44,40 +44,3 @@ jobs: uses: ./.github/actions/build-docs with: version: "${{ inputs.version }}" - - - - # artefact-1: - # name: "Artefact 1" - # runs-on: ubuntu-latest - # timeout-minutes: 3 - # steps: - # - name: "Checkout code" - # uses: actions/checkout@v5 - # - name: "Build artefact 1" - # run: | - # echo "Building artefact 1 ..." - # - name: "Check artefact 1" - # run: | - # echo "Checking artefact 1 ..." - # - name: "Upload artefact 1" - # run: | - # echo "Uploading artefact 1 ..." - # # Use either action/cache or action/upload-artifact - # artefact-n: - # name: "Artefact n" - # runs-on: ubuntu-latest - # timeout-minutes: 3 - # steps: - # - name: "Checkout code" - # uses: actions/checkout@v5 - # - name: "Build artefact n" - # run: | - # echo "Building artefact n ..." - # - name: "Check artefact n" - # run: | - # echo "Checking artefact n ..." - # - name: "Upload artefact n" - # run: | - # echo "Uploading artefact n ..." - # # Use either action/cache or action/upload-artifact diff --git a/Makefile b/Makefile index e7c3d75e4..206c0b9d7 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,9 @@ quick-start: config clean build serve-docs # Quick start target to setup, build dependencies: # Install dependencies needed to build and test the project @Pipeline # TODO: Implement installation of your project dependencies +generate: # Generate any autogenerated output @Pipeline + npm run generate-dependencies + build: # Build the project artefact @Pipeline $(MAKE) -C docs build @@ -30,12 +33,14 @@ clean:: # Clean-up project resources (main) @Operations $(MAKE) -C src/eventcatalogasyncapiimporter clean $(MAKE) -C src/eventcatalogasyncapiimporter clean-output rm -f .version - # TODO: Implement project resources clean-up step + npm run clean config:: _install-dependencies version # Configure development environment (main) @Configuration $(MAKE) -C docs install $(MAKE) -C src/cloudevents install $(MAKE) -C src/eventcatalogasyncapiimporter install + npm install + $(MAKE) generate serve-docs: $(MAKE) -C docs s @@ -50,5 +55,5 @@ ${VERBOSE}.SILENT: \ build \ clean \ config \ - dependencies \ + generate \ deploy \ diff --git a/README.md b/README.md index 32f28aed0..198d36d57 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,10 @@ Installation and configuration of the toolchain dependencies make config ``` +Note that the `make config` command will also build the flattened event schemas and auto-generate a Typescript +type and JS validator code for each event. See the [typescript-schema-generator](src/typescript-schema-generator/) +package for more details. + ## Usage ### Testing diff --git a/docs/Makefile b/docs/Makefile index c8043e22d..67775f361 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -43,7 +43,6 @@ build: clean build-schemas copy-schema-docs copy-schema-yaml-docs copy-schemas b build-ci: build-schemas-ci copy-schema-docs copy-schema-yaml-docs copy-schemas build-eventcatalog build-docs show-build-output - build-eventcatalog: $(MAKE) build-eventcatalog-prereq make -C $(EVENT_CAT_ROOT_DIR) build BASE_URL=$(EVENT_CAT_URL) diff --git a/infrastructure/terraform/components/dl/pre.sh b/infrastructure/terraform/components/dl/pre.sh index 40afad84b..870803e0c 100755 --- a/infrastructure/terraform/components/dl/pre.sh +++ b/infrastructure/terraform/components/dl/pre.sh @@ -6,6 +6,6 @@ npm ci -npm run generate-dependencies --workspaces --if-present +npm run generate-dependencies npm run lambda-build --workspaces --if-present diff --git a/lambdas/mesh-poll/package.json b/lambdas/mesh-poll/package.json index 226e78bd8..6844edd75 100644 --- a/lambdas/mesh-poll/package.json +++ b/lambdas/mesh-poll/package.json @@ -1,12 +1,13 @@ { "dependencies": { - "aws-lambda": "^1.0.7" + "aws-lambda": "^1.0.7", + "digital-letters-events": "^0.0.1" }, "devDependencies": { "@tsconfig/node22": "^22.0.2", "@types/aws-lambda": "^8.10.155", - "@types/jest": "^30.0.0", - "jest": "^30.2.0", + "@types/jest": "^29.5.14", + "jest": "^29.7.0", "jest-mock-extended": "^4.0.0", "typescript": "^5.9.3" }, diff --git a/lambdas/mesh-poll/src/__tests__/index.test.ts b/lambdas/mesh-poll/src/__tests__/index.test.ts index aad2cd40d..52398e0f5 100644 --- a/lambdas/mesh-poll/src/__tests__/index.test.ts +++ b/lambdas/mesh-poll/src/__tests__/index.test.ts @@ -1,12 +1,44 @@ import type { Context } from 'aws-lambda'; import { mockDeep } from 'jest-mock-extended'; +import { PDMResourceSubmitted } from 'digital-letters-events'; import { handler } from '..'; +const context = mockDeep(); +const callback = jest.fn(); + describe('event-logging Lambda', () => { it('logs the input event and returns 200', async () => { - const event = { foo: 'bar' }; - const context = mockDeep(); - const callback = jest.fn(); + const event: PDMResourceSubmitted = { + type: 'uk.nhs.notify.digital.letters.pdm.resource.submitted.v1', + source: + '/nhs/england/notify/staging/dev-647563337/data-plane/digitalletters/pdm', + dataschema: + 'https://notify.nhs.uk/cloudevents/schemas/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submitted-data.schema.json', + specversion: '1.0', + id: '0249e529-f947-4012-819e-b634eb71be79', + subject: + 'customer/7ff8ed41-cd5f-20e4-ef4e-34f96d8cc8ac/75027ace-9b8c-bcfe-866e-6c24242cffc3/q58dnxk5e/4cbek805wwx/yiaw7bl0d/her/1ccb7eb8-c6fe-0a42-279a-2a0e48ff1ca9/zk', + time: '2025-11-21T16:01:52.268Z', + datacontenttype: 'application/json', + traceparent: '00-ee4790eb6821064c645406abe918b3da-3a4e6957ce2a15de-01', + tracestate: 'nisi quis', + partitionkey: 'customer-7ff8ed41', + recordedtime: '2025-11-21T16:01:53.268Z', + sampledrate: 1, + sequence: '00000000000350773861', + severitytext: 'INFO', + severitynumber: 2, + dataclassification: 'restricted', + dataregulation: 'ISO-27001', + datacategory: 'non-sensitive', + data: { + messageReference: 'incididunt Ut aute laborum', + senderId: 'officia voluptate culpa Ut dolor', + resourceId: 'a2bcbb42-ab7e-42b6-88d6-74f8d3ca4a09', + retryCount: 97_903_257, + }, + }; + const result = await handler(event, context, callback); expect(result).toEqual({ @@ -14,4 +46,10 @@ describe('event-logging Lambda', () => { body: 'Event logged', }); }); + + it('throws an error if an invalid event is provided', async () => { + const invalidEvent = { foo: 'bar' }; + + await expect(handler(invalidEvent, context, callback)).rejects.toThrow(); + }); }); diff --git a/lambdas/mesh-poll/src/index.ts b/lambdas/mesh-poll/src/index.ts index 1b73d95c0..29f227a4f 100644 --- a/lambdas/mesh-poll/src/index.ts +++ b/lambdas/mesh-poll/src/index.ts @@ -1,9 +1,55 @@ +/* eslint-disable no-console -- Allowing console logging as this is an example file. */ // Replace me with the actual code for your Lambda function import { Handler } from 'aws-lambda'; +import { PDMResourceSubmitted } from 'digital-letters-events'; +import eventValidator from 'digital-letters-events/PDMResourceSubmitted.js'; -export const handler: Handler = async (event) => { - // eslint-disable-next-line no-console +export const handler: Handler = async (event: PDMResourceSubmitted) => { console.log('Received event:', event); + + // We can build a new PDMResourceSubmitted event object like this: + const pdmResourceSubmittedEvent: PDMResourceSubmitted = { + type: 'uk.nhs.notify.digital.letters.pdm.resource.submitted.v1', + source: + '/nhs/england/notify/staging/dev-647563337/data-plane/digitalletters/pdm', + dataschema: + 'https://notify.nhs.uk/cloudevents/schemas/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submitted-data.schema.json', + specversion: '1.0', + id: '0249e529-f947-4012-819e-b634eb71be79', + subject: + 'customer/7ff8ed41-cd5f-20e4-ef4e-34f96d8cc8ac/75027ace-9b8c-bcfe-866e-6c24242cffc3/q58dnxk5e/4cbek805wwx/yiaw7bl0d/her/1ccb7eb8-c6fe-0a42-279a-2a0e48ff1ca9/zk', + time: '2025-11-21T16:01:52.268Z', + datacontenttype: 'application/json', + traceparent: '00-ee4790eb6821064c645406abe918b3da-3a4e6957ce2a15de-01', + tracestate: 'nisi quis', + partitionkey: 'customer-7ff8ed41', + recordedtime: '2025-11-21T16:01:53.268Z', + sampledrate: 1, + sequence: '00000000000350773861', + severitytext: 'INFO', + severitynumber: 2, + dataclassification: 'restricted', + dataregulation: 'ISO-27001', + datacategory: 'non-sensitive', + data: { + messageReference: 'incididunt Ut aute laborum', + senderId: 'officia voluptate culpa Ut dolor', + resourceId: 'a2bcbb42-ab7e-42b6-88d6-74f8d3ca4a09', + retryCount: 97_903_257, + }, + }; + + console.log('PDM resource submitted event:', pdmResourceSubmittedEvent); + + // We can validate an event like this: + const isEventValid = eventValidator(event); + if (isEventValid) { + console.log('pdmResourceSubmittedEvent is valid!'); + } else { + console.error('Validation failure!', eventValidator.errors); + throw new Error('Event validation failed'); + } + return { statusCode: 200, body: 'Event logged', diff --git a/lambdas/mesh-poll/tsconfig.json b/lambdas/mesh-poll/tsconfig.json index ea37d6966..19a99d174 100644 --- a/lambdas/mesh-poll/tsconfig.json +++ b/lambdas/mesh-poll/tsconfig.json @@ -1,4 +1,8 @@ { + "compilerOptions": { + "allowJs": true, + "isolatedModules": true + }, "extends": "@tsconfig/node22/tsconfig.json", "include": [ "src/**/*", diff --git a/package-lock.json b/package-lock.json index e238fd024..d8dc228c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,8 @@ "utils/utils", "utils/sender-management", "src/cloudevents", + "src/digital-letters-events", + "src/typescript-schema-generator", "tests/playwright" ], "devDependencies": { @@ -147,17 +149,56 @@ "name": "nhs-notify-digital-letters-mesh-poll", "version": "0.0.1", "dependencies": { - "aws-lambda": "^1.0.7" + "aws-lambda": "^1.0.7", + "digital-letters-events": "^0.0.1" }, "devDependencies": { "@tsconfig/node22": "^22.0.2", "@types/aws-lambda": "^8.10.155", - "@types/jest": "^30.0.0", - "jest": "^30.2.0", + "@types/jest": "^29.5.14", + "jest": "^29.7.0", "jest-mock-extended": "^4.0.0", "typescript": "^5.9.3" } }, + "lambdas/mesh-poll/node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "lambdas/mesh-poll/node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, "lambdas/refresh-apim-access-token": { "version": "0.0.1", "dependencies": { @@ -3915,6 +3956,8 @@ }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", "dev": true, "license": "MIT", "dependencies": { @@ -3926,6 +3969,8 @@ }, "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4049,6 +4094,13 @@ "kuler": "^2.0.0" } }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "dev": true, + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.11", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz", @@ -4605,7 +4657,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.6", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4832,7 +4886,9 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -6845,22 +6901,30 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.11", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", "dev": true, "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true, "license": "MIT" }, @@ -7161,7 +7225,6 @@ }, "node_modules/@types/lodash": { "version": "4.17.20", - "dev": true, "license": "MIT" }, "node_modules/@types/lodash.clonedeep": { @@ -7172,6 +7235,16 @@ "@types/lodash": "*" } }, + "node_modules/@types/mock-fs": { + "version": "4.13.4", + "resolved": "https://registry.npmjs.org/@types/mock-fs/-/mock-fs-4.13.4.tgz", + "integrity": "sha512-mXmM0o6lULPI8z3XNnQCpL0BGxPwx1Ul1wXYEPBGl4efShyxW2Rln0JOPEWGyZaYZMM6OVXM/15zUuFMY52ljg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/ms": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", @@ -7183,6 +7256,7 @@ "version": "24.0.3", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.8.0" } @@ -7551,6 +7625,8 @@ }, "node_modules/acorn-walk": { "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", "dev": true, "license": "MIT", "dependencies": { @@ -7585,6 +7661,8 @@ }, "node_modules/ajv-cli": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", + "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", "dev": true, "license": "MIT", "dependencies": { @@ -7632,7 +7710,9 @@ } }, "node_modules/ajv-cli/node_modules/js-yaml": { - "version": "3.14.1", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "dev": true, "license": "MIT", "dependencies": { @@ -7650,6 +7730,8 @@ }, "node_modules/ajv-formats": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "license": "MIT", "dependencies": { "ajv": "^8.0.0" @@ -7729,6 +7811,8 @@ }, "node_modules/arg": { "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true, "license": "MIT" }, @@ -7960,7 +8044,9 @@ } }, "node_modules/aws-lambda/node_modules/js-yaml": { - "version": "3.14.1", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -8662,9 +8748,29 @@ }, "node_modules/create-require": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true, "license": "MIT" }, + "node_modules/cross-env": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", + "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "dev": true, @@ -8876,6 +8982,8 @@ }, "node_modules/diff": { "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -8894,6 +9002,10 @@ "resolved": "src/cloudevents", "link": true }, + "node_modules/digital-letters-events": { + "resolved": "src/digital-letters-events", + "link": true + }, "node_modules/doctrine": { "version": "2.1.0", "dev": true, @@ -12082,7 +12194,9 @@ } }, "node_modules/jest-html-reporter/node_modules/glob": { - "version": "10.4.5", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -12315,6 +12429,8 @@ }, "node_modules/jest-mock-extended": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-4.0.0.tgz", + "integrity": "sha512-7BZpfuvLam+/HC+NxifIi9b+5VXj/utUDMPUqrDJehGWVuXPtLS9Jqlob2mJLrI/pg2k1S8DMfKDvEB88QNjaQ==", "dev": true, "license": "MIT", "dependencies": { @@ -13101,7 +13217,9 @@ } }, "node_modules/jest/node_modules/glob": { - "version": "10.4.5", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -13668,7 +13786,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -13764,7 +13884,9 @@ } }, "node_modules/json-schema-faker/node_modules/js-yaml": { - "version": "3.14.1", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -13921,6 +14043,46 @@ "semver": "bin/semver.js" } }, + "node_modules/json-schema-to-typescript": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-15.0.4.tgz", + "integrity": "sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ==", + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^11.5.5", + "@types/json-schema": "^7.0.15", + "@types/lodash": "^4.17.7", + "is-glob": "^4.0.3", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "minimist": "^1.2.8", + "prettier": "^3.2.5", + "tinyglobby": "^0.2.9" + }, + "bin": { + "json2ts": "dist/src/cli.js" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/json-schema-to-typescript/node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.9.3", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.3.tgz", + "integrity": "sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==", + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "dev": true, @@ -14386,7 +14548,6 @@ }, "node_modules/minimist": { "version": "1.2.8", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -14418,6 +14579,16 @@ "obliterator": "^1.6.1" } }, + "node_modules/mock-fs": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.5.0.tgz", + "integrity": "sha512-d/P1M/RacgM3dB0sJ8rjeRNXxtapkPCUnMGmIN0ixJ16F/E4GUZCvWcSGfWGz8eaXYvn1s9baUwNjI4LOPEjiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/ms": { "version": "2.1.3", "license": "MIT" @@ -15061,8 +15232,9 @@ } }, "node_modules/prettier": { - "version": "3.6.0", - "dev": true, + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "license": "MIT", "peer": true, "bin": { @@ -15426,7 +15598,9 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.4.5", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "license": "ISC", "dependencies": { @@ -16153,7 +16327,6 @@ }, "node_modules/tinyglobby": { "version": "0.2.14", - "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.4.4", @@ -16168,7 +16341,6 @@ }, "node_modules/tinyglobby/node_modules/fdir": { "version": "6.4.6", - "dev": true, "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -16181,7 +16353,6 @@ }, "node_modules/tinyglobby/node_modules/picomatch": { "version": "4.0.2", - "dev": true, "license": "MIT", "peer": true, "engines": { @@ -16366,6 +16537,8 @@ }, "node_modules/ts-node": { "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", "peer": true, @@ -16574,6 +16747,8 @@ }, "node_modules/typescript": { "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -16608,6 +16783,10 @@ "typescript": ">=4.8.4 <6.0.0" } }, + "node_modules/typescript-schema-generator": { + "resolved": "src/typescript-schema-generator", + "link": true + }, "node_modules/uglify-js": { "version": "3.19.3", "dev": true, @@ -16752,6 +16931,8 @@ }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true, "license": "MIT" }, @@ -17164,6 +17345,8 @@ }, "node_modules/yn": { "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, "license": "MIT", "engines": { @@ -17207,7 +17390,7 @@ "jest": "^30.2.0", "json-schema-static-docs": "^0.28.1", "ts-jest": "^29.4.5", - "ts-node": "^10.0.0", + "tsx": "^4.20.6", "typescript": "^5.0.0" } }, @@ -17242,6 +17425,315 @@ "dev": true, "license": "MIT" }, + "src/digital-letters-events": { + "version": "0.0.1", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + }, + "devDependencies": { + "rimraf": "^5.0.10", + "typescript": "^5.9.3" + } + }, + "src/digital-letters-events/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "src/digital-letters-events/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "src/typescript-schema-generator": { + "version": "0.0.1", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "json-schema-to-typescript": "^15.0.4" + }, + "devDependencies": { + "@types/jest": "^29.5.14", + "@types/mock-fs": "^4.13.4", + "cross-env": "^10.1.0", + "eslint": "^9.39.1", + "jest": "^29.7.0", + "mock-fs": "^5.5.0", + "tsx": "^4.20.6" + } + }, + "src/typescript-schema-generator/node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "src/typescript-schema-generator/node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "src/typescript-schema-generator/node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "src/typescript-schema-generator/node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "src/typescript-schema-generator/node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "src/typescript-schema-generator/node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "src/typescript-schema-generator/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "src/typescript-schema-generator/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "src/typescript-schema-generator/node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "src/typescript-schema-generator/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "src/typescript-schema-generator/node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "src/typescript-schema-generator/node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "src/typescript-schema-generator/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "src/typescript-schema-generator/node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "src/typescript-schema-generator/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "src/typescript-schema-generator/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "tests/playwright": { "name": "nhs-notify-digital-letters-integration-tests", "version": "0.0.1", diff --git a/package.json b/package.json index a4768185e..df3f71100 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,8 @@ "react": "^19.0.0" }, "scripts": { - "generate-dependencies": "npm run generate-dependencies --workspaces --if-present", + "clean": "npm run clean --workspaces --if-present", + "generate-dependencies": "make -C src/cloudevents/domains/digital-letters build-no-bundle publish-bundled-json && npm run generate-dependencies --workspaces --if-present", "lint": "npm run lint --workspaces", "lint:fix": "npm run lint:fix --workspaces", "start": "npm run start --workspace frontend", @@ -59,6 +60,8 @@ "utils/utils", "utils/sender-management", "src/cloudevents", + "src/digital-letters-events", + "src/typescript-schema-generator", "tests/playwright" ] } diff --git a/src/cloudevents/domains/common.mk b/src/cloudevents/domains/common.mk index cb8c4aa9d..e96dcd34e 100644 --- a/src/cloudevents/domains/common.mk +++ b/src/cloudevents/domains/common.mk @@ -39,9 +39,20 @@ DATA_NAMES = $(sort $(patsubst %.yaml,%,$(notdir $(DATA_SCHEMAS)))) DEFS_NAMES = $(sort $(patsubst %.yaml,%,$(notdir $(DEFS_SCHEMAS)))) EVENT_NAMES = $(sort $(patsubst %.schema.yaml,%,$(notdir $(EVENT_SCHEMAS)))) -.PHONY: build publish publish-json publish-yaml generate test deploy clean +.PHONY: build build-no-bundle publish publish-json publish-bundled-json publish-yaml generate test deploy clean build: + $(MAKE) build-no-bundle + @if [ -n "$(EVENT_NAMES)" ]; then \ + echo "Bundling and flattening event schemas..."; \ + for schema in $(EVENT_NAMES); do \ + echo " - $$schema (bundle & flatten)"; \ + cd $(CLOUD_EVENTS_DIR) && npm run bundle -- --root-dir $(ROOT_DIR) $(OUTPUT_DIR)/events/$$schema.schema.json $(OUTPUT_DIR)/events/$$schema.bundle.schema.json || exit 1; \ + cd $(CLOUD_EVENTS_DIR) && npm run bundle -- --flatten --root-dir $(ROOT_DIR) $(OUTPUT_DIR)/events/$$schema.schema.json $(OUTPUT_DIR)/events/$$schema.flattened.schema.json || exit 1; \ + done; \ + fi + +build-no-bundle: @echo "Building $(DOMAIN) schemas to output/..." @if [ -n "$(PROFILE_NAMES)" ]; then \ echo "Building profile schemas..."; \ @@ -70,12 +81,6 @@ build: echo " - $$schema"; \ cd $(CLOUD_EVENTS_DIR) && npm run build -- --root-dir $(ROOT_DIR) $(SRC_DIR)/events/$$schema.schema.yaml $(OUTPUT_DIR)/events || exit 1; \ done; \ - echo "Bundling and flattening event schemas..."; \ - for schema in $(EVENT_NAMES); do \ - echo " - $$schema (bundle & flatten)"; \ - cd $(CLOUD_EVENTS_DIR) && npm run bundle -- --root-dir $(ROOT_DIR) $(OUTPUT_DIR)/events/$$schema.schema.json $(OUTPUT_DIR)/events/$$schema.bundle.schema.json || exit 1; \ - cd $(CLOUD_EVENTS_DIR) && npm run bundle -- --flatten --root-dir $(ROOT_DIR) $(OUTPUT_DIR)/events/$$schema.schema.json $(OUTPUT_DIR)/events/$$schema.flattened.schema.json || exit 1; \ - done; \ fi publish-json: @@ -123,10 +128,19 @@ publish-json: cd $(CLOUD_EVENTS_DIR) && npm run build -- --root-dir $(ROOT_DIR) $(SRC_DIR)/events/$$schema.schema.yaml $(SCHEMAS_DIR)/events $(SCHEMA_BASE_URL) || exit 1; \ fi; \ done; \ - echo "Bundling and flattening published event schemas..."; \ + echo "Bundling published event schemas..."; \ for schema in $(EVENT_NAMES); do \ - echo " - $$schema (bundle & flatten)"; \ + echo " - $$schema (bundle)"; \ cd $(CLOUD_EVENTS_DIR) && npm run bundle -- --root-dir $(ROOT_DIR) --base-url $(SCHEMA_BASE_URL) $(OUTPUT_DIR)/events/$$schema.schema.json $(SCHEMAS_DIR)/events/$$schema.bundle.schema.json || exit 1; \ + done; \ + fi + $(MAKE) publish-bundled-json + +publish-bundled-json: + @if [ -n "$(EVENT_NAMES)" ]; then \ + @echo "Flattening published event schemas..."; \ + for schema in $(EVENT_NAMES); do \ + echo " - $$schema (flatten)"; \ cd $(CLOUD_EVENTS_DIR) && npm run bundle -- --flatten --root-dir $(ROOT_DIR) --base-url $(SCHEMA_BASE_URL) $(OUTPUT_DIR)/events/$$schema.schema.json $(SCHEMAS_DIR)/events/$$schema.flattened.schema.json || exit 1; \ done; \ fi @@ -189,7 +203,7 @@ test: for schema in $(EVENT_NAMES); do \ echo "Testing $$schema event..."; \ echo "Discovering schema dependencies for $$schema..."; \ - SCHEMA_DEPS=$$(npx ts-node $(ROOT_DIR)/src/cloudevents/tools/discovery/discover-schema-dependencies.ts $(SRC_DIR)/events/$$schema.schema.yaml $(ROOT_DIR)/output 2>/dev/null); \ + SCHEMA_DEPS=$$(npx tsx $(ROOT_DIR)/src/cloudevents/tools/discovery/discover-schema-dependencies.ts $(SRC_DIR)/events/$$schema.schema.yaml $(ROOT_DIR)/output 2>/dev/null); \ if [ $$? -ne 0 ]; then \ echo "❌ Failed to discover dependencies for $$schema"; \ FAILED=1; \ diff --git a/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-available-data.schema.yaml b/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-available-data.schema.yaml index 5ea400d2e..4574efa79 100644 --- a/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-available-data.schema.yaml +++ b/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-available-data.schema.yaml @@ -1,6 +1,7 @@ $schema: https://json-schema.org/draft/2020-12/schema title: PDMResourceAvailable Data description: Base data of the PDMResourceAvailable event +type: object additionalProperties: false properties: messageReference: diff --git a/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-retries-exceeded-data.schema.yaml b/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-retries-exceeded-data.schema.yaml index 6fed13490..99e2e449c 100644 --- a/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-retries-exceeded-data.schema.yaml +++ b/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-retries-exceeded-data.schema.yaml @@ -1,6 +1,7 @@ $schema: https://json-schema.org/draft/2020-12/schema title: PDMResourceRetriesExceeded Data description: Base data of the PDMResourceRetriesExceeded event +type: object additionalProperties: false properties: messageReference: diff --git a/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submission-rejected-data.schema.yaml b/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submission-rejected-data.schema.yaml index 8f43e11ab..46f44b660 100644 --- a/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submission-rejected-data.schema.yaml +++ b/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submission-rejected-data.schema.yaml @@ -1,6 +1,7 @@ $schema: https://json-schema.org/draft/2020-12/schema title: PDMResourceSubmissionRejected Data description: Base data of the PDMResourceSubmissionRejected event +type: object additionalProperties: false properties: messageReference: diff --git a/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-unavailable-data.schema.yaml b/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-unavailable-data.schema.yaml index af7e5d812..2c5ed5e94 100644 --- a/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-unavailable-data.schema.yaml +++ b/src/cloudevents/domains/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-unavailable-data.schema.yaml @@ -1,6 +1,7 @@ $schema: https://json-schema.org/draft/2020-12/schema title: PDMResourceUnavailable Data description: Base data of the PDMResourceUnavailable event +type: object additionalProperties: false properties: messageReference: diff --git a/src/cloudevents/domains/digital-letters/Makefile b/src/cloudevents/domains/digital-letters/Makefile index 00211df4e..f43f42366 100644 --- a/src/cloudevents/domains/digital-letters/Makefile +++ b/src/cloudevents/domains/digital-letters/Makefile @@ -27,6 +27,6 @@ build publish publish-json publish-yaml generate test deploy clean: done else # Build specific version -build publish publish-json publish-yaml generate test deploy clean: +build build-no-bundle publish publish-json publish-bundled-json publish-yaml generate test deploy clean: @$(MAKE) -f ../common.mk $@ PUBLISH_VERSION=$(PUBLISH_VERSION) DOMAIN=$(DOMAIN) ROOT_DIR=$(ROOT_DIR) endif diff --git a/src/cloudevents/package-lock.json b/src/cloudevents/package-lock.json deleted file mode 100644 index 99312d020..000000000 --- a/src/cloudevents/package-lock.json +++ /dev/null @@ -1,1727 +0,0 @@ -{ - "name": "cloudevents-example-generator", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "cloudevents-example-generator", - "version": "1.0.0", - "dependencies": { - "@types/js-yaml": "^4.0.9", - "ajv": "^8.0.0", - "ajv-formats": "^3.0.1", - "js-yaml": "^4.1.0", - "json-schema-faker": "^0.5.0-rc23", - "json-schema-ref-parser": "^9.0.9" - }, - "devDependencies": { - "@types/node": "^20.0.0", - "ajv-cli": "^5.0.0", - "json-schema-static-docs": "^0.28.1", - "ts-node": "^10.0.0", - "typescript": "^5.0.0" - } - }, - "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==", - "license": "MIT", - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@jsdevtools/ono": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "license": "MIT" - }, - "node_modules/@jsep-plugin/assignment": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", - "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", - "license": "MIT", - "engines": { - "node": ">= 10.16.0" - }, - "peerDependencies": { - "jsep": "^0.4.0||^1.0.0" - } - }, - "node_modules/@jsep-plugin/regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", - "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", - "license": "MIT", - "engines": { - "node": ">= 10.16.0" - }, - "peerDependencies": { - "jsep": "^0.4.0||^1.0.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT" - }, - "node_modules/@types/lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/lodash.clonedeep": { - "version": "4.5.9", - "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.9.tgz", - "integrity": "sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/node": { - "version": "20.19.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.18.tgz", - "integrity": "sha512-KeYVbfnbsBCyKG8e3gmUqAfyZNcoj/qpEbHRkQkfZdKOBrU7QQ+BsTdfqLSWX9/m1ytYreMhpKvp+EZi3UFYAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-cli": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", - "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0", - "fast-json-patch": "^2.0.0", - "glob": "^7.1.0", - "js-yaml": "^3.14.0", - "json-schema-migrate": "^2.0.0", - "json5": "^2.1.3", - "minimist": "^1.2.0" - }, - "bin": { - "ajv": "dist/index.js" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, - "node_modules/ajv-cli/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/ajv-cli/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-patch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", - "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^2.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/fast-json-patch/node_modules/fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/format-util": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/format-util/-/format-util-1.0.5.tgz", - "integrity": "sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==", - "license": "MIT" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsep": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", - "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", - "license": "MIT", - "engines": { - "node": ">= 10.16.0" - } - }, - "node_modules/json-schema-faker": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/json-schema-faker/-/json-schema-faker-0.5.9.tgz", - "integrity": "sha512-fNKLHgDvfGNNTX1zqIjqFMJjCLzJ2kvnJ831x4aqkAoeE4jE2TxvpJdhOnk3JU3s42vFzmXvkpbYzH5H3ncAzg==", - "license": "MIT", - "dependencies": { - "json-schema-ref-parser": "^6.1.0", - "jsonpath-plus": "^10.3.0" - }, - "bin": { - "jsf": "bin/gen.cjs" - } - }, - "node_modules/json-schema-faker/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/json-schema-faker/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-faker/node_modules/json-schema-ref-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-6.1.0.tgz", - "integrity": "sha512-pXe9H1m6IgIpXmE5JSb8epilNTGsmTb2iPohAXpOdhqGFbQjNeHHsZxU+C8w6T81GZxSPFLeUoqDJmzxx5IGuw==", - "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", - "license": "MIT", - "dependencies": { - "call-me-maybe": "^1.0.1", - "js-yaml": "^3.12.1", - "ono": "^4.0.11" - } - }, - "node_modules/json-schema-migrate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", - "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - } - }, - "node_modules/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q==", - "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", - "license": "MIT", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "9.0.9" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/json-schema-static-docs": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/json-schema-static-docs/-/json-schema-static-docs-0.28.1.tgz", - "integrity": "sha512-Ti4UO5wK1GqWzCuij57twgfT04NSoluPgLlnf8Sz9ex6tVEgCM2Z1niRSDkZgw7C4MNJM9MCwGdjtUGSbjO/eA==", - "dev": true, - "license": "GPL-3.0-only", - "dependencies": { - "@apidevtools/json-schema-ref-parser": "^10.1.0", - "ajv": "^8.17.1", - "ajv-formats": "^3.0.1", - "extend": "^3.0.2", - "fast-glob": "^3.3.1", - "handlebars": "^4.7.7", - "jsonpointer": "^5.0.1", - "lodash": ">=4.17.21", - "make-dir": "^3.1.0", - "mkdirp": "^2.1.6", - "optimist": "^0.5.2", - "rimraf": "^5.0.10", - "yaml": "^2.2.2" - }, - "bin": { - "json-schema-static-docs": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/json-schema-static-docs/node_modules/@apidevtools/json-schema-ref-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-10.1.0.tgz", - "integrity": "sha512-3e+viyMuXdrcK8v5pvP+SDoAQ77FH6OyRmuK48SZKmdHJRFm87RsSs8qm6kP39a/pOPURByJw+OXzQIqcfmKtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.11", - "@types/lodash.clonedeep": "^4.5.7", - "js-yaml": "^4.1.0", - "lodash.clonedeep": "^4.5.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/philsturgeon" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonpath-plus": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz", - "integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==", - "license": "MIT", - "dependencies": { - "@jsep-plugin/assignment": "^1.3.0", - "@jsep-plugin/regex": "^1.0.4", - "jsep": "^1.4.0" - }, - "bin": { - "jsonpath": "bin/jsonpath-cli.js", - "jsonpath-plus": "bin/jsonpath-cli.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", - "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/ono": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/ono/-/ono-4.0.11.tgz", - "integrity": "sha512-jQ31cORBFE6td25deYeD80wxKBMj+zBmHTrVxnc6CKhx8gho6ipmWM5zj/oeoqioZ99yqBls9Z/9Nss7J26G2g==", - "license": "MIT", - "dependencies": { - "format-util": "^1.0.3" - } - }, - "node_modules/optimist": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.5.2.tgz", - "integrity": "sha512-r9M8ZpnM9SXV5Wii7TCqienfcaY3tAiJe9Jchof87icbmbruKgK0xKXngmrnowTDnEawmmI1Qbha59JEoBkBGA==", - "dev": true, - "license": "MIT/X11", - "dependencies": { - "wordwrap": "~0.0.2" - } - }, - "node_modules/optimist/node_modules/wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause" - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - } - } -} diff --git a/src/cloudevents/package.json b/src/cloudevents/package.json index 8fe82eda2..e81a70ae4 100644 --- a/src/cloudevents/package.json +++ b/src/cloudevents/package.json @@ -16,21 +16,21 @@ "jest": "^30.2.0", "json-schema-static-docs": "^0.28.1", "ts-jest": "^29.4.5", - "ts-node": "^10.0.0", + "tsx": "^4.20.6", "typescript": "^5.0.0" }, "main": "tools/generator/example-generator/generate-example.ts", "name": "digital-letters-cloudevents-schemas", "scripts": { - "build": "ts-node tools/builder/build-schema.ts", - "build-docs": "ts-node tools/generator/docs-generator/generate-docs-cli.ts", - "bundle": "ts-node tools/generator/manual-bundler/manual-bundle-schema.ts", - "bundle:old": "ts-node tools/generator/bundle-schema.ts", - "bundle:prefer-child": "ts-node tools/generator/bundle-schema-prefer-child.ts", - "cache-info": "ts-node tools/generator/example-generator/generate-example.ts --cache-info", - "clear-cache": "ts-node tools/generator/example-generator/generate-example.ts --clear-cache", - "generate": "ts-node tools/generator/example-generator/generate-example.ts $@", - "json-to-yaml": "ts-node tools/generator/json-to-yaml/index.ts", + "build": "tsx tools/builder/build-schema.ts", + "build-docs": "tsx tools/generator/docs-generator/generate-docs-cli.ts", + "bundle": "tsx tools/generator/manual-bundler/manual-bundle-schema.ts", + "bundle:old": "tsx tools/generator/bundle-schema.ts", + "bundle:prefer-child": "tsx tools/generator/bundle-schema-prefer-child.ts", + "cache-info": "tsx tools/generator/example-generator/generate-example.ts --cache-info", + "clear-cache": "tsx tools/generator/example-generator/generate-example.ts --clear-cache", + "generate": "tsx tools/generator/example-generator/generate-example.ts $@", + "json-to-yaml": "tsx tools/generator/json-to-yaml/index.ts", "lint": "echo 'no linting configured'", "lint:fix": "echo 'no linting configured'", "test": "jest", @@ -38,8 +38,8 @@ "test:unit": "jest --coverage; node -e \"const fs = require('fs'); fs.mkdirSync('.reports/unit/coverage', {recursive: true}); fs.copyFileSync('coverage/lcov.info', '.reports/unit/coverage/lcov.info');\"", "test:watch": "jest --watch", "typecheck": "echo 'no typechecking configured'", - "update-readme": "ts-node tools/generator/readme-generator/update-readme-cli.ts", - "validate": "ts-node tools/validator/validate.ts $@" + "update-readme": "tsx tools/generator/readme-generator/update-readme-cli.ts", + "validate": "tsx tools/validator/validate.ts $@" }, "type": "module", "version": "1.0.0" diff --git a/src/cloudevents/tools/builder/__tests__/build-schema.test.ts b/src/cloudevents/tools/builder/__tests__/build-schema.test.ts index ae7f2b647..f7c35f908 100644 --- a/src/cloudevents/tools/builder/__tests__/build-schema.test.ts +++ b/src/cloudevents/tools/builder/__tests__/build-schema.test.ts @@ -50,7 +50,7 @@ describe('build-schema CLI', () => { // Run build-schema try { execSync( - `ts-node tools/builder/build-schema.ts "${inputFile}" "${outputDir}"`, + `tsx tools/builder/build-schema.ts "${inputFile}" "${outputDir}"`, { cwd: process.cwd(), stdio: 'pipe' @@ -89,7 +89,7 @@ properties: try { execSync( - `ts-node tools/builder/build-schema.ts "${inputFile}" "${outputDir}"`, + `tsx tools/builder/build-schema.ts "${inputFile}" "${outputDir}"`, { cwd: process.cwd(), stdio: 'pipe' @@ -118,7 +118,7 @@ properties: try { const result = execSync( - `ts-node tools/builder/build-schema.ts "${inputFile}" "${outputDir}"`, + `tsx tools/builder/build-schema.ts "${inputFile}" "${outputDir}"`, { cwd: process.cwd(), stdio: 'pipe', @@ -137,7 +137,7 @@ properties: it('should handle missing arguments gracefully', () => { try { execSync( - 'ts-node tools/builder/build-schema.ts', + 'tsx tools/builder/build-schema.ts', { cwd: process.cwd(), stdio: 'pipe' @@ -158,7 +158,7 @@ properties: try { execSync( - `ts-node tools/builder/build-schema.ts "${inputFile}" "${outputDir}" "https://example.com"`, + `tsx tools/builder/build-schema.ts "${inputFile}" "${outputDir}" "https://example.com"`, { cwd: process.cwd(), stdio: 'pipe' @@ -196,7 +196,7 @@ properties: try { // Build the main schema execSync( - `ts-node tools/builder/build-schema.ts "${mainFile}" "${outputDir}"`, + `tsx tools/builder/build-schema.ts "${mainFile}" "${outputDir}"`, { cwd: process.cwd(), stdio: 'pipe' @@ -222,7 +222,7 @@ properties: try { execSync( - `ts-node tools/builder/build-schema.ts "${yamlFile}" "${outputDir}"`, + `tsx tools/builder/build-schema.ts "${yamlFile}" "${outputDir}"`, { cwd: process.cwd(), stdio: 'pipe' @@ -244,7 +244,7 @@ properties: it('should handle non-existent input file', () => { try { execSync( - `ts-node tools/builder/build-schema.ts "nonexistent.json" "${outputDir}"`, + `tsx tools/builder/build-schema.ts "nonexistent.json" "${outputDir}"`, { cwd: process.cwd(), stdio: 'pipe' @@ -264,7 +264,7 @@ properties: try { execSync( - `ts-node tools/builder/build-schema.ts "${invalidFile}" "${outputDir}"`, + `tsx tools/builder/build-schema.ts "${invalidFile}" "${outputDir}"`, { cwd: process.cwd(), stdio: 'pipe' diff --git a/src/cloudevents/tools/builder/build-schema-cli.ts b/src/cloudevents/tools/builder/build-schema-cli.ts index 003071af1..c2bb3c542 100644 --- a/src/cloudevents/tools/builder/build-schema-cli.ts +++ b/src/cloudevents/tools/builder/build-schema-cli.ts @@ -353,11 +353,11 @@ export function handleCli(args: string[]): CliResult { if (!sourceSchemaPath || !outputDir) { const errorMsg = [ - "Usage: ts-node build-schema.ts [--root-dir ] [--strip-prefix ] [base-url]", - "Example: ts-node build-schema.ts src/common/2025-10/nhs-notify-profile.schema.yaml output/common/2025-10", - "With URL: ts-node build-schema.ts src/common/2025-10/nhs-notify-profile.schema.yaml output/common/2025-10 https://schema.notify.nhs.uk", - "With root: ts-node build-schema.ts --root-dir /path/to/repo src/common/2025-10/nhs-notify-profile.schema.yaml output/common/2025-10", - "With strip prefix: ts-node build-schema.ts --strip-prefix cloudevents/domains src/common/2025-10/nhs-notify-profile.schema.yaml output/common/2025-10 https://schema.notify.nhs.uk" + "Usage: tsx build-schema.ts [--root-dir ] [--strip-prefix ] [base-url]", + "Example: tsx build-schema.ts src/common/2025-10/nhs-notify-profile.schema.yaml output/common/2025-10", + "With URL: tsx build-schema.ts src/common/2025-10/nhs-notify-profile.schema.yaml output/common/2025-10 https://schema.notify.nhs.uk", + "With root: tsx build-schema.ts --root-dir /path/to/repo src/common/2025-10/nhs-notify-profile.schema.yaml output/common/2025-10", + "With strip prefix: tsx build-schema.ts --strip-prefix cloudevents/domains src/common/2025-10/nhs-notify-profile.schema.yaml output/common/2025-10 https://schema.notify.nhs.uk" ].join("\n"); console.error(errorMsg); diff --git a/src/cloudevents/tools/builder/build-schema.ts b/src/cloudevents/tools/builder/build-schema.ts index e840248be..b1adf912a 100644 --- a/src/cloudevents/tools/builder/build-schema.ts +++ b/src/cloudevents/tools/builder/build-schema.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env tsx import { handleCli } from "./build-schema-cli.ts"; diff --git a/src/cloudevents/tools/discovery/__tests__/discover-schema-dependencies.test.ts b/src/cloudevents/tools/discovery/__tests__/discover-schema-dependencies.test.ts index 30a009af8..501429ec4 100644 --- a/src/cloudevents/tools/discovery/__tests__/discover-schema-dependencies.test.ts +++ b/src/cloudevents/tools/discovery/__tests__/discover-schema-dependencies.test.ts @@ -8,7 +8,7 @@ import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals'; import fs from 'fs'; import path from 'path'; -import { execSync } from 'child_process'; +import { execFileSync } from 'child_process'; import os from 'os'; const SCRIPT_PATH = path.resolve(__dirname, '../discover-schema-dependencies.ts'); @@ -31,13 +31,13 @@ describe('discover-schema-dependencies CLI', () => { describe('CLI argument validation', () => { it('should exit with error when no arguments provided', () => { expect(() => { - execSync(`npx ts-node ${SCRIPT_PATH}`, { encoding: 'utf-8', stdio: 'pipe' }); + execFileSync('npx', ['tsx', SCRIPT_PATH], { encoding: 'utf-8', stdio: 'pipe' }); }).toThrow(); }); it('should exit with error when only one argument provided', () => { expect(() => { - execSync(`npx ts-node ${SCRIPT_PATH} /some/path`, { + execFileSync('npx', ['tsx', SCRIPT_PATH, '/some/path'], { encoding: 'utf-8', stdio: 'pipe', }); @@ -49,7 +49,7 @@ describe('discover-schema-dependencies CLI', () => { const outputDir = path.join(tempDir, 'output'); expect(() => { - execSync(`npx ts-node ${SCRIPT_PATH} ${nonExistentPath} ${outputDir}`, { + execFileSync('npx', ['tsx', SCRIPT_PATH, nonExistentPath, outputDir], { encoding: 'utf-8', stdio: 'pipe', }); @@ -77,7 +77,7 @@ properties: const outputDir = path.join(tempDir, 'output'); fs.mkdirSync(outputDir, { recursive: true }); - const result = execSync(`npx ts-node ${SCRIPT_PATH} ${schemaPath} ${outputDir}`, { + const result = execFileSync('npx', ['tsx', SCRIPT_PATH, schemaPath, outputDir], { encoding: 'utf-8', }); @@ -126,7 +126,7 @@ properties: const outputDir = path.join(tempDir, 'output'); fs.mkdirSync(outputDir, { recursive: true }); - const result = execSync(`npx ts-node ${SCRIPT_PATH} ${schemaPath} ${outputDir}`, { + const result = execFileSync('npx', ['tsx', SCRIPT_PATH, schemaPath, outputDir], { encoding: 'utf-8', }); @@ -178,7 +178,7 @@ properties: fs.mkdirSync(outputDir, { recursive: true }); // Should complete without hanging or error - const result = execSync(`npx ts-node ${SCRIPT_PATH} ${schemaAPath} ${outputDir}`, { + const result = execFileSync('npx', ['tsx', SCRIPT_PATH, schemaAPath, outputDir], { encoding: 'utf-8', timeout: 5000, // 5 second timeout to catch infinite loops }); @@ -209,7 +209,7 @@ properties: const outputDir = path.join(tempDir, 'output'); fs.mkdirSync(outputDir, { recursive: true }); - const result = execSync(`npx ts-node ${SCRIPT_PATH} ${schemaPath} ${outputDir}`, { + const result = execFileSync('npx', ['tsx', SCRIPT_PATH, schemaPath, outputDir], { encoding: 'utf-8', }); @@ -236,7 +236,7 @@ properties: const outputDir = path.join(tempDir, 'output'); fs.mkdirSync(outputDir, { recursive: true }); - const result = execSync(`npx ts-node ${SCRIPT_PATH} ${schemaPath} ${outputDir}`, { + const result = execFileSync('npx', ['tsx', SCRIPT_PATH, schemaPath, outputDir], { encoding: 'utf-8', }); @@ -276,7 +276,7 @@ properties: const outputDir = path.join(tempDir, 'output'); fs.mkdirSync(outputDir, { recursive: true }); - const result = execSync(`npx ts-node ${SCRIPT_PATH} ${schema1Path} ${outputDir}`, { + const result = execFileSync('npx', ['tsx', SCRIPT_PATH, schema1Path, outputDir], { encoding: 'utf-8', }); @@ -310,7 +310,7 @@ properties: const outputDir = path.join(tempDir, 'output'); fs.mkdirSync(outputDir, { recursive: true }); - const result = execSync(`npx ts-node ${SCRIPT_PATH} ${eventPath} ${outputDir}`, { + const result = execFileSync('npx', ['tsx', SCRIPT_PATH, eventPath, outputDir], { encoding: 'utf-8', }); diff --git a/src/cloudevents/tools/generator/__tests__/generate-docs-cli.test.ts b/src/cloudevents/tools/generator/__tests__/generate-docs-cli.test.ts index ae2b69c52..d31eb2a4b 100644 --- a/src/cloudevents/tools/generator/__tests__/generate-docs-cli.test.ts +++ b/src/cloudevents/tools/generator/__tests__/generate-docs-cli.test.ts @@ -138,7 +138,7 @@ describe('generate-docs-cli', () => { printUsage(); expect(consoleErrorMock).toHaveBeenCalledWith( - expect.stringContaining('Usage: ts-node generate-docs-cli.ts') + expect.stringContaining('Usage: tsx generate-docs-cli.ts') ); expect(consoleErrorMock).toHaveBeenCalledWith(expect.stringContaining('Example:')); }); diff --git a/src/cloudevents/tools/generator/__tests__/generate-docs.test.ts b/src/cloudevents/tools/generator/__tests__/generate-docs.test.ts index 9eb5e86c3..bfd749df8 100644 --- a/src/cloudevents/tools/generator/__tests__/generate-docs.test.ts +++ b/src/cloudevents/tools/generator/__tests__/generate-docs.test.ts @@ -68,14 +68,14 @@ describe('generate-docs TypeScript', () => { const result = await runGenerateDocs([]); expect(result.exitCode).toBe(1); - expect(result.stderr).toContain('Usage: ts-node generate-docs-cli.ts '); + expect(result.stderr).toContain('Usage: tsx generate-docs-cli.ts '); }); it('should fail when only one argument is provided', async () => { const result = await runGenerateDocs([INPUT_DIR]); expect(result.exitCode).toBe(1); - expect(result.stderr).toContain('Usage: ts-node generate-docs-cli.ts '); + expect(result.stderr).toContain('Usage: tsx generate-docs-cli.ts '); }); it('should fail when input directory does not exist', async () => { diff --git a/src/cloudevents/tools/generator/__tests__/generate-example-cli.test.ts b/src/cloudevents/tools/generator/__tests__/generate-example-cli.test.ts index 81dd2b8ad..d2c4a3d2d 100644 --- a/src/cloudevents/tools/generator/__tests__/generate-example-cli.test.ts +++ b/src/cloudevents/tools/generator/__tests__/generate-example-cli.test.ts @@ -57,7 +57,7 @@ describe('generate-example-cli', () => { await handleCli([]); const errorOutput = consoleErrorMock.mock.calls[0][0]; - expect(errorOutput).toContain('Usage: ts-node generate-example.ts'); + expect(errorOutput).toContain('Usage: tsx generate-example.ts'); expect(errorOutput).toContain('--clear-cache'); expect(errorOutput).toContain('--cache-info'); expect(errorOutput).toContain('SCHEMA_CACHE_DIR'); diff --git a/src/cloudevents/tools/generator/__tests__/generate-example.test.ts b/src/cloudevents/tools/generator/__tests__/generate-example.test.ts index 7b5c9d9c7..ea5f1e206 100644 --- a/src/cloudevents/tools/generator/__tests__/generate-example.test.ts +++ b/src/cloudevents/tools/generator/__tests__/generate-example.test.ts @@ -11,8 +11,8 @@ import http from 'http'; const SCRIPT_PATH = path.join(__dirname, '..', 'example-generator', 'generate-example.ts'); const TEST_DIR = path.join(__dirname, 'temp-generate-example-test'); -// Use npx to run ts-node, which will find it in the root workspace -const TS_NODE_CMD = 'npx ts-node'; +// Use npx to run tsx, which will find it in the root workspace +const TS_NODE_CMD = 'npx tsx'; describe('generate-example.ts', () => { let server: http.Server | undefined; diff --git a/src/cloudevents/tools/generator/__tests__/json-to-yaml.test.ts b/src/cloudevents/tools/generator/__tests__/json-to-yaml.test.ts index b6f5c84d1..ef7ec1aba 100644 --- a/src/cloudevents/tools/generator/__tests__/json-to-yaml.test.ts +++ b/src/cloudevents/tools/generator/__tests__/json-to-yaml.test.ts @@ -524,7 +524,7 @@ describe('handleCli', () => { expect(handleCli(['arg1', 'arg2', 'arg3'])).toBe(1); expect(consoleSpy).toHaveBeenCalledWith( - 'Usage: ts-node json-to-yaml-cli.ts ' + 'Usage: tsx json-to-yaml-cli.ts ' ); consoleSpy.mockRestore(); diff --git a/src/cloudevents/tools/generator/docs-generator/generate-docs-cli.ts b/src/cloudevents/tools/generator/docs-generator/generate-docs-cli.ts index b927bd02c..89b2347e6 100644 --- a/src/cloudevents/tools/generator/docs-generator/generate-docs-cli.ts +++ b/src/cloudevents/tools/generator/docs-generator/generate-docs-cli.ts @@ -75,8 +75,8 @@ export function ensureOutputDir(outputDir: string): { success: boolean; error?: * Print CLI usage information */ export function printUsage(): void { - console.error('Usage: ts-node generate-docs-cli.ts '); - console.error('Example: ts-node generate-docs-cli.ts ./output ./docs'); + console.error('Usage: tsx generate-docs-cli.ts '); + console.error('Example: tsx generate-docs-cli.ts ./output ./docs'); } /** diff --git a/src/cloudevents/tools/generator/example-generator/generate-example-cli.ts b/src/cloudevents/tools/generator/example-generator/generate-example-cli.ts index 14d2909c2..123bf1101 100644 --- a/src/cloudevents/tools/generator/example-generator/generate-example-cli.ts +++ b/src/cloudevents/tools/generator/example-generator/generate-example-cli.ts @@ -40,9 +40,9 @@ export async function handleCli(args: string[]): Promise { const [schemaPathRaw, outputPath] = args; if (!schemaPathRaw || !outputPath) { const errorMsg = [ - "Usage: ts-node generate-example.ts ", - " ts-node generate-example.ts --clear-cache", - " ts-node generate-example.ts --cache-info", + "Usage: tsx generate-example.ts ", + " tsx generate-example.ts --clear-cache", + " tsx generate-example.ts --cache-info", "", "Environment variables:", " SCHEMA_CACHE_DIR - Custom cache directory (default: system tmp)" diff --git a/src/cloudevents/tools/generator/json-to-yaml/index.ts b/src/cloudevents/tools/generator/json-to-yaml/index.ts index ac9547c16..4bde9d181 100644 --- a/src/cloudevents/tools/generator/json-to-yaml/index.ts +++ b/src/cloudevents/tools/generator/json-to-yaml/index.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env tsx /** * Entry point for json-to-yaml CLI tool * This file runs the CLI handler when executed directly diff --git a/src/cloudevents/tools/generator/json-to-yaml/json-to-yaml-cli.ts b/src/cloudevents/tools/generator/json-to-yaml/json-to-yaml-cli.ts index 67dbf6a76..65c69cff2 100644 --- a/src/cloudevents/tools/generator/json-to-yaml/json-to-yaml-cli.ts +++ b/src/cloudevents/tools/generator/json-to-yaml/json-to-yaml-cli.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env tsx /** * CLI handler for json-to-yaml conversion @@ -19,7 +19,7 @@ import { JsonToYamlConverter } from './json-to-yaml-converter.ts'; export function handleCli(args: string[]): number { // Validate argument count if (args.length !== 2) { - console.error('Usage: ts-node json-to-yaml-cli.ts '); + console.error('Usage: tsx json-to-yaml-cli.ts '); return 1; } diff --git a/src/cloudevents/tools/generator/manual-bundler/manual-bundle-schema-cli.ts b/src/cloudevents/tools/generator/manual-bundler/manual-bundle-schema-cli.ts index bfa762760..85806684a 100644 --- a/src/cloudevents/tools/generator/manual-bundler/manual-bundle-schema-cli.ts +++ b/src/cloudevents/tools/generator/manual-bundler/manual-bundle-schema-cli.ts @@ -64,9 +64,9 @@ export async function handleCli(args: string[]): Promise { // Validate arguments if (!entry || !outFile) { const errorMsg = [ - 'Usage: ts-node manual-bundle-schema.ts [--flatten] [--root-dir ] [--base-url ] ', - ' ts-node manual-bundle-schema.ts --clear-cache', - ' ts-node manual-bundle-schema.ts --cache-info', + 'Usage: tsx manual-bundle-schema.ts [--flatten] [--root-dir ] [--base-url ] ', + ' tsx manual-bundle-schema.ts --clear-cache', + ' tsx manual-bundle-schema.ts --cache-info', '', 'Environment variables:', ' SCHEMA_CACHE_DIR - Custom cache directory (default: system tmp)' diff --git a/src/cloudevents/tools/generator/manual-bundler/schema-bundler.ts b/src/cloudevents/tools/generator/manual-bundler/schema-bundler.ts index 891131b9c..6bd705f37 100644 --- a/src/cloudevents/tools/generator/manual-bundler/schema-bundler.ts +++ b/src/cloudevents/tools/generator/manual-bundler/schema-bundler.ts @@ -422,11 +422,9 @@ export class SchemaBundler { // Load and process schema const entrySchema = this.loadSchema(entryPath); - let processedSchema: SchemaObject; + let processedSchema: SchemaObject = this.dereferencePropertiesOnly(entrySchema, entryPath, false); if (this.options.flatten) { - processedSchema = await this.flattenAllOf(entrySchema, entryPath); - } else { - processedSchema = this.dereferencePropertiesOnly(entrySchema, entryPath, false); + processedSchema = await this.flattenAllOf(processedSchema, entryPath); } // Post-process: convert relative refs to external URLs if baseUrl provided diff --git a/src/cloudevents/tools/validator/__tests__/validate.test.ts b/src/cloudevents/tools/validator/__tests__/validate.test.ts index d0417d183..0ff4ab5db 100644 --- a/src/cloudevents/tools/validator/__tests__/validate.test.ts +++ b/src/cloudevents/tools/validator/__tests__/validate.test.ts @@ -17,9 +17,9 @@ const TEST_DIR = path.join(__dirname, 'temp-validate-test'); function runValidator(schemaPath: string, dataPath: string, baseDir?: string): { success: boolean; output: string; error: string } { try { const args = baseDir ? ['--base', baseDir, schemaPath, dataPath] : [schemaPath, dataPath]; - const result = spawnSync('npx', ['ts-node', SCRIPT_PATH, ...args], { + const result = spawnSync('npx', ['tsx', SCRIPT_PATH, ...args], { encoding: 'utf-8', - timeout: 10000 // Increased timeout for ts-node + timeout: 10000 // Increased timeout for tsx }); return { @@ -53,7 +53,7 @@ describe('validate.ts', () => { describe('command line arguments', () => { it('should exit with error when no arguments provided', () => { - const result = spawnSync('npx', ['ts-node', SCRIPT_PATH], { encoding: 'utf-8', timeout: 10000 }); + const result = spawnSync('npx', ['tsx', SCRIPT_PATH], { encoding: 'utf-8', timeout: 10000 }); expect(result.status).not.toBe(0); expect(result.stderr).toContain('Usage:'); }); @@ -62,7 +62,7 @@ describe('validate.ts', () => { const schemaFile = path.join(TEST_DIR, 'schema.json'); fs.writeFileSync(schemaFile, JSON.stringify({ type: 'object' })); - const result = spawnSync('node', [SCRIPT_PATH, schemaFile], { encoding: 'utf-8' }); + const result = spawnSync('npx', ['tsx', SCRIPT_PATH, schemaFile], { encoding: 'utf-8', timeout: 10000 }); expect(result.status).not.toBe(0); expect(result.stderr).toContain('Usage:'); }); diff --git a/src/cloudevents/tools/validator/validate.ts b/src/cloudevents/tools/validator/validate.ts index 74e2bbde1..98aaa2b0f 100644 --- a/src/cloudevents/tools/validator/validate.ts +++ b/src/cloudevents/tools/validator/validate.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env tsx /** * CLI wrapper for JSON Schema validation * diff --git a/src/digital-letters-events/.gitignore b/src/digital-letters-events/.gitignore new file mode 100644 index 000000000..abb5d782c --- /dev/null +++ b/src/digital-letters-events/.gitignore @@ -0,0 +1,2 @@ +validators +types diff --git a/src/digital-letters-events/README.md b/src/digital-letters-events/README.md new file mode 100644 index 000000000..6177d8115 --- /dev/null +++ b/src/digital-letters-events/README.md @@ -0,0 +1,76 @@ +# digital-letters-events + +This package contains the automatically-generated code that the +[typescript-schema-generator](../typescript-schema-generator/) tool produces. + +The source files in this package should not be edited directly. If changes are +required, update the schemas in the +[src/cloudevents/domains](../cloudevents/domains) directory and use the +`typescript-schema-generator` tool to regenerate them. + +## Using this Package + +### Using Event Types + +The event types can be used by simply installing the +`digital-letters-events` package as a dependency and then importing +the desired type: + +```typescript +import { PDMResourceSubmitted } from 'digital-letters-events'; + +const pdmResourceSubmittedEvent: PDMResourceSubmitted = { + type: 'uk.nhs.notify.digital.letters.pdm.resource.submitted.v1', + source: + '/nhs/england/notify/staging/dev-647563337/data-plane/digitalletters/pdm', + dataschema: + 'https://notify.nhs.uk/cloudevents/schemas/digital-letters/2025-10-draft/data/digital-letters-pdm-resource-submitted-data.schema.json', + specversion: '1.0', + id: '0249e529-f947-4012-819e-b634eb71be79', + subject: + 'customer/7ff8ed41-cd5f-20e4-ef4e-34f96d8cc8ac/75027ace-9b8c-bcfe-866e-6c24242cffc3/q58dnxk5e/4cbek805wwx/yiaw7bl0d/her/1ccb7eb8-c6fe-0a42-279a-2a0e48ff1ca9/zk', + time: '2025-11-21T16:01:52.268Z', + datacontenttype: 'application/json', + traceparent: '00-ee4790eb6821064c645406abe918b3da-3a4e6957ce2a15de-01', + tracestate: 'nisi quis', + partitionkey: 'customer-7ff8ed41', + recordedtime: '2025-11-21T16:01:53.268Z', + sampledrate: 1, + sequence: '00000000000350773861', + severitytext: 'INFO', + severitynumber: 2, + dataclassification: 'restricted', + dataregulation: 'ISO-27001', + datacategory: 'non-sensitive', + data: { + messageReference: 'incididunt Ut aute laborum', + senderId: 'officia voluptate culpa Ut dolor', + resourceId: 'a2bcbb42-ab7e-42b6-88d6-74f8d3ca4a09', + retryCount: 97_903_257, + }, + }; +``` + +### Using Event Validator Functions + +Validator functions for an event can be used by importing the default export +from the relevant JS file in +[`validators`](validators/): + +```typescript +import eventValidator from 'digital-letters-events/PDMResourceSubmitted.js'; + +const event = {}; + +const isEventValid = eventValidator(event); +if (isEventValid) { + console.log('Event is valid!'); +} else { + console.error('Validation failure!', eventValidator.errors); + throw new Error('Event validation failed'); +} +``` + +Note: You will need to make sure the +[`allowJs`](https://www.typescriptlang.org/tsconfig/#allowJs) option is set in +your package's `tsconfig.json` in order to import the JS files. diff --git a/src/digital-letters-events/package.json b/src/digital-letters-events/package.json new file mode 100644 index 000000000..f42ae8f19 --- /dev/null +++ b/src/digital-letters-events/package.json @@ -0,0 +1,29 @@ +{ + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + }, + "description": "Generated Typescript types and standalone validator functions for the application's event schemas.", + "devDependencies": { + "rimraf": "^5.0.10", + "typescript": "^5.9.3" + }, + "exports": { + ".": { + "types": "./types/index.d.ts" + }, + "./*.js": { + "default": "./validators/*.js", + "types": "./validators/index.d.ts" + } + }, + "name": "digital-letters-events", + "scripts": { + "clean": "rimraf types validators", + "lint": "echo \"No linter has been implemented for this package.\"", + "lint:fix": "echo \"No linter has been implemented for this package.\"", + "test:unit": "echo \"No unit tests have been implemented for this package.\"", + "typecheck": "tsc --noEmit" + }, + "version": "0.0.1" +} diff --git a/src/digital-letters-events/tsconfig.json b/src/digital-letters-events/tsconfig.json new file mode 100644 index 000000000..c2099752d --- /dev/null +++ b/src/digital-letters-events/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "allowJs": true, + "isolatedModules": true, + "outDir": "dist" + }, + "exclude": [ + "node_modules" + ], + "extends": "@tsconfig/node22/tsconfig.json", + "include": [ + "validators/**/*", + "types/**/*" + ] +} diff --git a/src/typescript-schema-generator/README.md b/src/typescript-schema-generator/README.md new file mode 100644 index 000000000..74675f6da --- /dev/null +++ b/src/typescript-schema-generator/README.md @@ -0,0 +1,41 @@ +# typescript-schema-generator + +This package provides a tool that generates Typescript types and Javascript +validator functions for the events that are defined in the JSON schemas that +are built as part of this repository. + +## Setup + +Use `npm install` to install the necessary dependencies for this application. +This can be done from either the root of this repository or from this package's +directory. + +## Generating Code + +In order for this tool to function, you must first build the JSON schemas for +the Digital Letters events. The simplest way to build these schemas and +use this tool to automatically generate both types and validators is to run the +`npm run generate-dependencies` command from the root of this repository. + +This will produce the following: + +- Flattened JSON Event schemas in the [`schemas`](../../schemas/) directory +- A full set of JSON schemas in the [`output`](../../output/) directory +- A type definition for each event in the [`src/digital-letters-events/types`](../digital-letters-events/types/) directory +- A validator function for each event in the [`src/digital-letters-events/validators`](../digital-letters-events/validators/) directory + +### Generating Types + +Once the JSON schemas have been built, types can be generated on their own by +running the `generate-types` script from this package. This will update the +type definitions in the +[`src/digital-letters-events/types`](../digital-letters-events/types/) +directory only. + +### Generating Validators + +Once the JSON schemas have been built, the validation functions can be +generated on their own by running the `generate-validators` script from this +package. This will update the validator functions in the +[`src/digital-letters-events/validators`](../digital-letters-events/validators/) +directory only. diff --git a/src/typescript-schema-generator/jest.config.ts b/src/typescript-schema-generator/jest.config.ts new file mode 100644 index 000000000..a02be289f --- /dev/null +++ b/src/typescript-schema-generator/jest.config.ts @@ -0,0 +1,12 @@ +import { baseJestConfig } from '../../jest.config.base'; + +const config = { + ...baseJestConfig, + coveragePathIgnorePatterns: [ + ...(baseJestConfig.coveragePathIgnorePatterns ?? []), + 'src/generate-types-cli.ts', + 'src/generate-validators-cli.ts', + ], +}; + +export default config; diff --git a/src/typescript-schema-generator/package.json b/src/typescript-schema-generator/package.json new file mode 100644 index 000000000..23b74e9e6 --- /dev/null +++ b/src/typescript-schema-generator/package.json @@ -0,0 +1,29 @@ +{ + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "json-schema-to-typescript": "^15.0.4" + }, + "description": "A tool to generate Typescript types and standalone validator functions for the application's event schemas.", + "devDependencies": { + "@types/jest": "^29.5.14", + "@types/mock-fs": "^4.13.4", + "cross-env": "^10.1.0", + "eslint": "^9.39.1", + "jest": "^29.7.0", + "mock-fs": "^5.5.0", + "tsx": "^4.20.6" + }, + "name": "typescript-schema-generator", + "private": true, + "scripts": { + "generate-dependencies": "npm run generate-types && npm run generate-validators", + "generate-types": "tsx src/generate-types-cli.ts", + "generate-validators": "tsx src/generate-validators-cli.ts", + "lint": "eslint src", + "lint:fix": "eslint src --fix", + "test:unit": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest", + "typecheck": "tsc --noEmit" + }, + "version": "0.0.1" +} diff --git a/src/typescript-schema-generator/src/__tests__/generate-types.test.ts b/src/typescript-schema-generator/src/__tests__/generate-types.test.ts new file mode 100644 index 000000000..444f0cbd5 --- /dev/null +++ b/src/typescript-schema-generator/src/__tests__/generate-types.test.ts @@ -0,0 +1,68 @@ +/* eslint-disable security/detect-non-literal-fs-filename */ + +import { destinationPackageName, eventSchemasDir } from 'file-utils'; +import { generateTypes } from 'generate-types'; +import { compile } from 'json-schema-to-typescript'; +import mockFs from 'mock-fs'; +import { readFileSync, readdirSync } from 'node:fs'; +import path from 'node:path'; + +jest.mock('json-schema-to-typescript'); + +describe('generate-types', () => { + const outputDir = path.resolve( + __dirname, + '..', + '..', + '..', + destinationPackageName, + 'types', + ); + + beforeEach(() => { + mockFs({ + [eventSchemasDir]: { + 'one.flattened.schema.json': '{"title": "One"}', + 'two.flattened.schema.json': '{"title": "Two"}', + 'three.flattened.schema.json': '{"title": "Three"}', + }, + }); + + jest.mocked(compile).mockResolvedValue('Some TS code'); + + jest.spyOn(console, 'log').mockImplementation(() => {}); + jest.spyOn(console, 'group').mockImplementation(() => {}); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it('should generate a type declaration file for each schema', async () => { + await generateTypes(); + + const typeDeclarationFiles = readdirSync(outputDir); + + expect(typeDeclarationFiles.length).toBe(4); + expect(typeDeclarationFiles).toEqual( + expect.arrayContaining([ + 'index.d.ts', + 'One.d.ts', + 'Two.d.ts', + 'Three.d.ts', + ]), + ); + }); + + it('should create an index file exporting all generated types', async () => { + await generateTypes(); + + const indexFileContents = readFileSync( + path.join(outputDir, 'index.d.ts'), + 'utf8', + ); + expect(indexFileContents).toContain("export * from './One';"); + expect(indexFileContents).toContain("export * from './Two';"); + expect(indexFileContents).toContain("export * from './Three';"); + }); +}); diff --git a/src/typescript-schema-generator/src/__tests__/generate-validators.test.ts b/src/typescript-schema-generator/src/__tests__/generate-validators.test.ts new file mode 100644 index 000000000..00b7467d0 --- /dev/null +++ b/src/typescript-schema-generator/src/__tests__/generate-validators.test.ts @@ -0,0 +1,69 @@ +/* eslint-disable security/detect-non-literal-fs-filename */ +import standaloneCode from 'ajv/dist/standalone'; +import { destinationPackageName, eventSchemasDir } from 'file-utils'; +import { generateValidators } from 'generate-validators'; +import mockFs from 'mock-fs'; +import { readFileSync, readdirSync } from 'node:fs'; +import path from 'node:path'; + +jest.mock('ajv/dist/2020'); +jest.mock('ajv/dist/standalone'); + +describe('generate-validators', () => { + const outputDir = path.resolve( + __dirname, + '..', + '..', + '..', + destinationPackageName, + 'validators', + ); + + beforeEach(() => { + mockFs({ + [eventSchemasDir]: { + 'one.flattened.schema.json': '{"title": "One"}', + 'two.flattened.schema.json': '{"title": "Two"}', + 'three.flattened.schema.json': '{"title": "Three"}', + }, + }); + + jest.mocked(standaloneCode).mockReturnValue('Some validator code'); + + jest.spyOn(console, 'log').mockImplementation(() => {}); + jest.spyOn(console, 'group').mockImplementation(() => {}); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it('should generate a validator function file for each schema', () => { + generateValidators(); + + const validatorFunctionFiles = readdirSync(outputDir); + + expect(validatorFunctionFiles.length).toBe(4); // 3 schemas + 1 index file + expect(validatorFunctionFiles).toEqual( + expect.arrayContaining(['One.js', 'Two.js', 'Three.js']), + ); + }); + + it('should create an index file declaring modules for all generated files', () => { + generateValidators(); + + const indexFileContents = readFileSync( + path.join(outputDir, 'index.d.ts'), + 'utf8', + ); + expect(indexFileContents).toContain( + `declare module '${destinationPackageName}/One.js';`, + ); + expect(indexFileContents).toContain( + `declare module '${destinationPackageName}/Two.js';`, + ); + expect(indexFileContents).toContain( + `declare module '${destinationPackageName}/Three.js';`, + ); + }); +}); diff --git a/src/typescript-schema-generator/src/file-utils.ts b/src/typescript-schema-generator/src/file-utils.ts new file mode 100644 index 000000000..f325cfb8c --- /dev/null +++ b/src/typescript-schema-generator/src/file-utils.ts @@ -0,0 +1,84 @@ +// We don't accept user input, so path traversal attacks should not be a risk. +/* eslint-disable security/detect-non-literal-fs-filename */ + +import { mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs'; +import path from 'node:path'; + +export const eventSchemasDir = path.resolve( + __dirname, + '..', + '..', + '..', + 'schemas', + 'digital-letters', + '2025-10-draft', + 'events', +); + +export const destinationPackageName = 'digital-letters-events'; + +/** + * Lists all event schema filenames in the digital letters schemas directory. + * + * @returns An array of schema filenames. + */ +export function listEventSchemas(): string[] { + const flattenedSchemaFiles = readdirSync(eventSchemasDir).filter((f) => + f.endsWith('.flattened.schema.json'), + ); + + return flattenedSchemaFiles; +} + +/** + * Loads and parses a JSON schema from the specified file path. + * + * @param schemaPath The path to the JSON schema file. + * @returns The parsed JSON schema object. + */ +export function loadSchema(schemaPath: string): any { + return JSON.parse(readFileSync(schemaPath, 'utf8')); +} + +/** + * Creates the specified output directory if it doesn't exist. + * + * @param dirName The name of the directory to create. + * @returns The resolved path to the created directory. + */ +export function createOutputDir(dirName: string): string { + const outputDir = path.resolve( + __dirname, + '..', + '..', + destinationPackageName, + dirName, + ); + mkdirSync(outputDir, { recursive: true }); + return outputDir; +} + +/** + * Write a file with the specified content to the given path and filename. + * + * @param outputDir The directory the file will be written to. + * @param fileName The name of the file to write. + * @param content The content to write to the file. + */ +export function writeFile( + outputDir: string, + fileName: string, + content: string, +): void { + writeFileSync(path.join(outputDir, fileName), content); +} + +/** + * Write an index.d.ts file containing all lines provided. + * + * @param outputDir The output directory where the index.d.ts file will be written. + * @param lines The lines to write to the index.d.ts file. + */ +export function writeTypesIndex(outputDir: string, lines: string[]): void { + writeFileSync(path.join(outputDir, 'index.d.ts'), `${lines.join('\n')}\n`); +} diff --git a/src/typescript-schema-generator/src/generate-types-cli.ts b/src/typescript-schema-generator/src/generate-types-cli.ts new file mode 100644 index 000000000..8b80e8192 --- /dev/null +++ b/src/typescript-schema-generator/src/generate-types-cli.ts @@ -0,0 +1,8 @@ +/* eslint-disable no-console */ + +import { generateTypes } from 'generate-types'; + +generateTypes().catch((error) => { + console.error('Error generating types:', error); + throw error; +}); diff --git a/src/typescript-schema-generator/src/generate-types.ts b/src/typescript-schema-generator/src/generate-types.ts new file mode 100644 index 000000000..e84f0772b --- /dev/null +++ b/src/typescript-schema-generator/src/generate-types.ts @@ -0,0 +1,41 @@ +/* eslint-disable no-console */ +import { compile } from 'json-schema-to-typescript'; +import path from 'node:path'; +import { + createOutputDir, + eventSchemasDir, + listEventSchemas, + loadSchema, + writeFile, + writeTypesIndex, +} from 'file-utils'; + +export async function generateTypes() { + const eventSchemaFilenames = listEventSchemas(); + const outputDir = createOutputDir('types'); + console.log(`Output directory created at ${outputDir}`); + + console.group('Writing type declaration files:'); + const indexLines: string[] = []; + for (const eventSchemaFilename of eventSchemaFilenames) { + const eventSchemaPath = path.join(eventSchemasDir, eventSchemaFilename); + const eventSchema = loadSchema(eventSchemaPath); + const typeName = eventSchema.title; + + const eventTs = await compile(eventSchema, eventSchema.title, { + additionalProperties: false, + }); + + // Write a .d.ts file named after the schema title or file. + const typeDeclarationFilename = `${typeName}.d.ts`; + writeFile(outputDir, typeDeclarationFilename, eventTs); + console.log(typeDeclarationFilename); + + // Also create an export statement for this type. + indexLines.push(`export * from './${typeName}';`); + } + console.groupEnd(); + + writeTypesIndex(outputDir, indexLines); + console.log('index.d.ts file written'); +} diff --git a/src/typescript-schema-generator/src/generate-validators-cli.ts b/src/typescript-schema-generator/src/generate-validators-cli.ts new file mode 100644 index 000000000..6bc0420fc --- /dev/null +++ b/src/typescript-schema-generator/src/generate-validators-cli.ts @@ -0,0 +1,3 @@ +import { generateValidators } from 'generate-validators'; + +generateValidators(); diff --git a/src/typescript-schema-generator/src/generate-validators.ts b/src/typescript-schema-generator/src/generate-validators.ts new file mode 100644 index 000000000..662dd58b8 --- /dev/null +++ b/src/typescript-schema-generator/src/generate-validators.ts @@ -0,0 +1,54 @@ +/* eslint-disable no-console */ +import path from 'node:path'; + +// Note: We are using the Ajv 2020 version to support JSON Schema draft 2020-12. +import Ajv from 'ajv/dist/2020'; + +import standaloneCode from 'ajv/dist/standalone'; +import { + createOutputDir, + destinationPackageName, + eventSchemasDir, + listEventSchemas, + loadSchema, + writeFile, + writeTypesIndex, +} from 'file-utils'; + +export function generateValidators() { + const ajv = new Ajv({ + code: { source: true, lines: true }, + + // Required because our schemas use the unknown keyword "name". + strictSchema: false, + }); + + const eventSchemaFilenames = listEventSchemas(); + const outputDir = createOutputDir('validators'); + console.log(`Output directory created at ${outputDir}`); + + // Generate a standalone validator for each schema. + console.group('Writing validator function files:'); + const moduleDeclarations: string[] = []; + for (const eventSchemaFilename of eventSchemaFilenames) { + const eventSchemaPath = path.join(eventSchemasDir, eventSchemaFilename); + const eventSchema = loadSchema(eventSchemaPath); + const validatorFilename = `${eventSchema.title}.js`; + + const validatorFn = ajv.compile(eventSchema); + const standaloneValidatorCode = standaloneCode(ajv, validatorFn); + + // Write the standalone validator to a .js file. + writeFile(outputDir, validatorFilename, standaloneValidatorCode); + console.log(validatorFilename); + + // Also create a module declaration for this validator. + moduleDeclarations.push( + `declare module '${destinationPackageName}/${validatorFilename}';`, + ); + } + console.groupEnd(); + + writeTypesIndex(outputDir, moduleDeclarations); + console.log('index.d.ts file written'); +} diff --git a/src/typescript-schema-generator/tsconfig.json b/src/typescript-schema-generator/tsconfig.json new file mode 100644 index 000000000..718b17e85 --- /dev/null +++ b/src/typescript-schema-generator/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "baseUrl": "./src/", + "isolatedModules": true, + "outDir": "dist" + }, + "exclude": [ + "node_modules" + ], + "extends": "@tsconfig/node22/tsconfig.json", + "include": [ + "src/**/*", + "./jest.config.ts" + ] +}