diff --git a/README.md b/README.md index 3462abf..ab2d26f 100644 --- a/README.md +++ b/README.md @@ -102,6 +102,7 @@ Usage: * [Usage guide](https://node-file-router.js.org/docs/usage-guide) * [Configuration](https://node-file-router.js.org/docs/usage-guide#configuration) * [Usage with Bun](https://node-file-router.js.org/docs/use-with-bun) +* [Get All Registered Routes](https://node-file-router.js.org/docs/usage-guide#get-all-registered-routes) Methods routing: * [Any method](https://node-file-router.js.org/docs/usage-guide#any-method) diff --git a/examples/web-socket/package.json b/examples/web-socket/package.json index a00ef87..b39566d 100644 --- a/examples/web-socket/package.json +++ b/examples/web-socket/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "node-file-router": "workspace:../../dist", - "ws": "8.16.0" + "ws": "8.18.0" }, "devDependencies": { "@types/node": "20.1.4", diff --git a/examples/web-socket/pnpm-lock.yaml b/examples/web-socket/pnpm-lock.yaml index ca3f78e..3395391 100644 --- a/examples/web-socket/pnpm-lock.yaml +++ b/examples/web-socket/pnpm-lock.yaml @@ -1,111 +1,90 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - node-file-router: - specifier: workspace:../../dist - version: link:../../dist - ws: - specifier: 8.16.0 - version: 8.16.0 - -devDependencies: - '@types/node': - specifier: 20.1.4 - version: 20.1.4 - '@types/ws': - specifier: 8.5.4 - version: 8.5.4 - ts-node: - specifier: 10.9.1 - version: 10.9.1(@types/node@20.1.4)(typescript@5.0.4) - typescript: - specifier: 5.0.4 - version: 5.0.4 +importers: + + .: + dependencies: + node-file-router: + specifier: workspace:../../dist + version: link:../../dist + ws: + specifier: 8.18.0 + version: 8.18.0 + devDependencies: + '@types/node': + specifier: 20.1.4 + version: 20.1.4 + '@types/ws': + specifier: 8.5.4 + version: 8.5.4 + ts-node: + specifier: 10.9.1 + version: 10.9.1(@types/node@20.1.4)(typescript@5.0.4) + typescript: + specifier: 5.0.4 + version: 5.0.4 packages: - /@cspotcode/source-map-support@0.8.1: + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - /@jridgewell/resolve-uri@3.1.1: + '@jridgewell/resolve-uri@3.1.1': resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} engines: {node: '>=6.0.0'} - dev: true - /@jridgewell/sourcemap-codec@1.4.15: + '@jridgewell/sourcemap-codec@1.4.15': resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - /@jridgewell/trace-mapping@0.3.9: + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - /@tsconfig/node10@1.0.9: + '@tsconfig/node10@1.0.9': resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true - /@tsconfig/node12@1.0.11: + '@tsconfig/node12@1.0.11': resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - /@tsconfig/node14@1.0.3: + '@tsconfig/node14@1.0.3': resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - /@tsconfig/node16@1.0.4: + '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true - /@types/node@20.1.4: + '@types/node@20.1.4': resolution: {integrity: sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q==} - dev: true - /@types/ws@8.5.4: + '@types/ws@8.5.4': resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} - dependencies: - '@types/node': 20.1.4 - dev: true - /acorn-walk@8.2.0: + acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} - dev: true - /acorn@8.8.2: + acorn@8.8.2: resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} engines: {node: '>=0.4.0'} hasBin: true - dev: true - /arg@4.1.3: + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - /create-require@1.1.1: + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - /diff@4.0.2: + diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} - dev: true - /make-error@1.3.6: + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - /ts-node@10.9.1(@types/node@20.1.4)(typescript@5.0.4): + ts-node@10.9.1: resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -118,6 +97,73 @@ packages: optional: true '@swc/wasm': optional: true + + typescript@5.0.4: + resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} + engines: {node: '>=12.20'} + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + +snapshots: + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@jridgewell/resolve-uri@3.1.1': {} + + '@jridgewell/sourcemap-codec@1.4.15': {} + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + + '@tsconfig/node10@1.0.9': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + + '@types/node@20.1.4': {} + + '@types/ws@8.5.4': + dependencies: + '@types/node': 20.1.4 + + acorn-walk@8.2.0: {} + + acorn@8.8.2: {} + + arg@4.1.3: {} + + create-require@1.1.1: {} + + diff@4.0.2: {} + + make-error@1.3.6: {} + + ts-node@10.9.1(@types/node@20.1.4)(typescript@5.0.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 @@ -134,32 +180,11 @@ packages: typescript: 5.0.4 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: true - /typescript@5.0.4: - resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} - engines: {node: '>=12.20'} - hasBin: true - dev: true + typescript@5.0.4: {} - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true + v8-compile-cache-lib@3.0.1: {} - /ws@8.16.0: - resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: false + ws@8.18.0: {} - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true + yn@3.1.1: {} diff --git a/package.json b/package.json index 3007511..ff110c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-file-router", - "version": "0.7.0", + "version": "0.8.0", "description": "A powerful file-based routing for Express.js, Bun, pure Node.js and more", "scripts": { "dev:sandbox": "tsnd examples/sandbox/server.ts", diff --git a/src/components/file-route-resolver.ts b/src/components/file-route-resolver.ts index b4e2fcc..2885797 100644 --- a/src/components/file-route-resolver.ts +++ b/src/components/file-route-resolver.ts @@ -4,8 +4,8 @@ import path from 'node:path'; import { exactSlugSegment } from './dynamic-routes/exact-slug-segment'; import { catchAllSegment } from './dynamic-routes/catch-all-segment'; import { optionalCatchAllSegment } from './dynamic-routes/optional-catch-all-segment'; -import { RouteHandler } from './route-handler/route-handler'; -import { MiddlewareHandler } from './route-handler/middleware-handler'; +import { Route } from './route/route'; +import { Middleware } from './route/middleware'; import { isCommonJs } from '../utils/env.utils'; import { validateFileFormat } from '../validations/validations'; @@ -54,7 +54,7 @@ export class FileRouteResolver { async getHandlers( directory = this.baseDir - ): Promise<[MiddlewareHandler[], RouteHandler[]]> { + ): Promise<[Middleware[], Route[]]> { const [middlewares, routes] = await this.scanDirectory(directory); return [ @@ -67,24 +67,24 @@ export class FileRouteResolver { directory = this.baseDir, parentRoute = '', nestingLevel = 0 - ): Promise<[MiddlewareHandler[], RouteHandler[]]> { + ): Promise<[Middleware[], Route[]]> { const entries = await fs.readdir(directory, { withFileTypes: true }); - const routeHandlers: RouteHandler[] = []; - const middlewareHandlers: MiddlewareHandler[] = []; + const routes: Route[] = []; + const middlewares: Middleware[] = []; for (const entry of entries) { - const [middlewares, routes] = await this.processEntry( + const [childMiddlewares, childRoutes] = await this.processEntry( directory, parentRoute, nestingLevel, entry ); - routeHandlers.push(...routes); - middlewareHandlers.push(...middlewares); + routes.push(...childRoutes); + middlewares.push(...childMiddlewares); } - return [middlewareHandlers, routeHandlers]; + return [middlewares, routes]; } private async processEntry( @@ -93,42 +93,42 @@ export class FileRouteResolver { nestingLevel: number, entry: Dirent ) { - const routeHandlers: RouteHandler[] = []; - const middlewareHandlers: MiddlewareHandler[] = []; + const routes: Route[] = []; + const middlewares: Middleware[] = []; const fullPath = path.join(directory, entry.name); const routePath = `${parentRoute}/${entry.name}`; if (entry.isDirectory()) { - const [childMiddlewareHandlers, childHandlers] = await this.scanDirectory( + const [childMiddlewares, childRoutes] = await this.scanDirectory( fullPath, routePath, nestingLevel + 1 ); - routeHandlers.push(...childHandlers); - middlewareHandlers.push(...childMiddlewareHandlers); + routes.push(...childRoutes); + middlewares.push(...childMiddlewares); } else if (entry.isFile() && this.isValidFile(entry.name)) { if (FileRouteResolver.middlewareFilePattern.test(entry.name)) { - const middlewareHandler = await this.processMiddlewareEntry( + const middleware = await this.processMiddlewareEntry( fullPath, routePath, nestingLevel ); - middlewareHandlers.push(middlewareHandler); + middlewares.push(middleware); } else { - const routeHandler = await this.processFileEntry( + const route = await this.processFileEntry( fullPath, entry, routePath, nestingLevel ); - routeHandlers.push(routeHandler); + routes.push(route); } } - return [middlewareHandlers, routeHandlers] as const; + return [middlewares, routes] as const; } private isValidFile(name: string): boolean { @@ -139,10 +139,7 @@ export class FileRouteResolver { return FileRouteResolver.fileExtensionPattern.test(name); } - private compareByNestingLevelAndType( - left: RouteHandler, - right: RouteHandler - ): number { + private compareByNestingLevelAndType(left: Route, right: Route): number { if (left.nestingLevel !== right.nestingLevel) { return right.nestingLevel - left.nestingLevel; } @@ -174,7 +171,7 @@ export class FileRouteResolver { '' ); - return new MiddlewareHandler({ + return new Middleware({ path: routePath, handler, nestingLevel @@ -186,7 +183,7 @@ export class FileRouteResolver { entry: Dirent, routePath: string, nestingLevel: number - ): Promise { + ): Promise { if (this.clearImportCache) { delete require.cache[fullPath]; } @@ -209,15 +206,17 @@ export class FileRouteResolver { const isIndex = FileRouteResolver.indexFilePattern.test(entry.name); const routeKey = isIndex ? route.replace(/\/index$/, '') : route; - const regex = new RegExp(`^${routeKey}/?$`); + const formattedUrlPath = + (isIndex ? pureRouteName.replace(/\/index$/, '') : pureRouteName) || '/'; - return new RouteHandler({ + return new Route({ method, fileName: entry.name, handler, - regex, + regex: new RegExp(`^${routeKey}/?$`), nestingLevel, - paramExtractors + paramExtractors, + urlPath: formattedUrlPath }); } diff --git a/src/components/route-handler/middleware-handler.ts b/src/components/route/middleware.ts similarity index 92% rename from src/components/route-handler/middleware-handler.ts rename to src/components/route/middleware.ts index ff581d4..97167c2 100644 --- a/src/components/route-handler/middleware-handler.ts +++ b/src/components/route/middleware.ts @@ -4,7 +4,7 @@ interface Props { nestingLevel: number; } -export class MiddlewareHandler { +export class Middleware { regexp: RegExp; handler: (...args: unknown[]) => Promise; nestingLevel: number; diff --git a/src/components/route-handler/route-handler.ts b/src/components/route/route.ts similarity index 95% rename from src/components/route-handler/route-handler.ts rename to src/components/route/route.ts index 9e80fd7..37da4e5 100644 --- a/src/components/route-handler/route-handler.ts +++ b/src/components/route/route.ts @@ -13,14 +13,16 @@ interface Props { regex: RegExp; paramExtractors: Record; nestingLevel: number; + urlPath: string; } -export class RouteHandler { +export class Route { method?: string; fileName: string; handler: RequestHandler | Record; regex: RegExp; nestingLevel: number; + urlPath: string; private paramExtractors: Record; diff --git a/src/file-router.ts b/src/file-router.ts index 83ceb72..325ffea 100644 --- a/src/file-router.ts +++ b/src/file-router.ts @@ -8,21 +8,28 @@ import { httpAdapter } from './adapters/http-adapter'; import { validateBaseDirExistence } from './validations/validations'; import { executeWithMiddlewares } from './components/middleware-executer'; -import type { Adapter } from './types/adapter'; import type { RequestHandler } from './types/request-handlers'; +import type { Adapter } from './types/adapter'; +import type { Route } from './components/route/route'; + +interface InitParams { + routes: Route[]; +} interface Options { baseDir?: string; ignoreFilesRegex?: RegExp[]; adapter?: Adapter; clearImportCache?: boolean; + onInit?: (params: InitParams) => void; } export async function initFileRouter({ baseDir = 'api', ignoreFilesRegex, clearImportCache = false, - adapter = httpAdapter + adapter = httpAdapter, + onInit }: Options = {}) { const { getPathname, defaultNotFoundHandler, getMethod } = adapter; @@ -90,6 +97,10 @@ export async function initFileRouter({ return notFoundHandler(...args, routeParams); } + if (onInit) { + onInit({ routes: routeHandlers }); + } + return function requestHandler(...args: unknown[]) { const pathname = getPathname(...args); const method = getMethod ? getMethod(...args) : undefined; diff --git a/src/index.ts b/src/index.ts index 53b9823..40272a8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,3 +3,4 @@ export type { NextFunction, FileRouterRequestHandler } from './types/request-handlers'; +export { Route } from './components/route/route'; diff --git a/tests/request-handle-initialization.test.ts b/tests/request-handle-initialization.test.ts new file mode 100644 index 0000000..68c217c --- /dev/null +++ b/tests/request-handle-initialization.test.ts @@ -0,0 +1,138 @@ +import { createTestRequestRunner } from './test-utils'; +import { initFileRouter } from '../src'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import type { Route } from '../src'; + +const currentCwd = process.cwd(); +vi.mock('process', () => ({ + cwd: () => `${currentCwd}/tests` +})); + +describe('RequestHandler', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('#Initialization', () => { + it('should init file router with the default params', async () => { + const requestHandler = await initFileRouter(); + + const run = createTestRequestRunner(requestHandler); + const { filePath } = await run('/'); + + expect(filePath).toBe('/api/index.ts'); + }); + + it('should init file router with an absolute path', async () => { + const baseDir = `${process.cwd()}/tests/api`; + const requestHandler = await initFileRouter({ baseDir }); + const run = createTestRequestRunner(requestHandler); + + const { filePath } = await run('/'); + + expect(filePath).toBe('/api/index.ts'); + }); + + it('should take the method in file names from the initialize callback.', async () => { + const baseDir = `${process.cwd()}/tests/api-methods-in-files`; + let actualRoutes: Route[]; + await initFileRouter({ + baseDir, + onInit: ({ routes }) => { + actualRoutes = routes; + } + }); + + expect(actualRoutes).toMatchObject([ + { + method: 'get', + urlPath: '/dynamic/catch-all/[...params]', + handler: expect.any(Function) + }, + { + method: 'get', + urlPath: '/dynamic/exact/[slug]', + handler: expect.any(Function) + }, + { + method: 'get', + urlPath: '/dynamic/optional-catch-all/[[...params]]', + handler: expect.any(Function) + }, + { + method: 'get', + urlPath: '/plain/some-route', + handler: expect.any(Function) + }, + { + method: 'post', + urlPath: '/plain/some-route', + handler: expect.any(Function) + }, + { + method: 'get', + urlPath: '/root', + handler: expect.any(Function) + }, + { + method: 'post', + urlPath: '/root', + handler: expect.any(Function) + } + ]); + }); + + it('should take the method in file names from the initialize callback.', async () => { + const baseDir = `${process.cwd()}/tests/api-basics`; + let actualRoutes: Route[]; + await initFileRouter({ + ignoreFilesRegex: [/^_.*$/, /.\.some-spec/], + baseDir, + onInit: ({ routes }) => { + actualRoutes = routes; + } + }); + + expect(actualRoutes).toMatchObject([ + { + fileName: '[id].ts', + handler: { + get: expect.any(Function), + post: expect.any(Function) + }, + urlPath: '/one/[id]/two/multi-methods/[id]' + }, + { + fileName: '[id].ts', + handler: expect.any(Function), + urlPath: '/one/[id]/two/three/[id]' + }, + { + fileName: 'index.ts', + handler: expect.any(Function), + urlPath: '/one/[id]/two' + }, + { + fileName: '[subId].ts', + handler: expect.any(Function), + urlPath: '/one/[id]/two/[subId]' + }, + { + fileName: 'index.ts', + handler: expect.any(Function), + urlPath: '/one/[id]' + }, + { + fileName: 'index.ts', + handler: expect.any(Function), + urlPath: '/' + }, + { + fileName: 'example.ts', + handler: expect.any(Function), + urlPath: '/example' + } + ]); + }); + }); +}); diff --git a/tests/request-handle-middlewares.test.ts b/tests/request-handle-middlewares.test.ts new file mode 100644 index 0000000..9fe0a77 --- /dev/null +++ b/tests/request-handle-middlewares.test.ts @@ -0,0 +1,212 @@ +import { + createTestMiddlewareRequestRunner, + createTestRequestRunner +} from './test-utils'; +import { initFileRouter } from '../src'; +import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; +import type { FileRouterRequestHandler } from '../src'; + +const currentCwd = process.cwd(); +vi.mock('process', () => ({ + cwd: () => `${currentCwd}/tests` +})); + +describe('RequestHandler', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('#Middlewares', () => { + let middlewaresRequestHandler: FileRouterRequestHandler; + + beforeAll(async () => { + middlewaresRequestHandler = await initFileRouter({ + baseDir: 'api-middlewares' + }); + }); + + it('should run the root middleware', async () => { + const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); + + const { marks } = await run('/'); + + expect(marks).toEqual(['before:m-root', 'root-index', 'after:m-root']); + }); + + it('should run the root middleware for dynamic route', async () => { + const runForMiddleware = createTestMiddlewareRequestRunner( + middlewaresRequestHandler + ); + const runForRoute = createTestRequestRunner(middlewaresRequestHandler); + + const { marks } = await runForMiddleware('/nested/123'); + expect(marks).toEqual(['before:m-root', '[id]', 'after:m-root']); + const { routeParams } = await runForRoute('/nested/123'); + expect(routeParams).toEqual({ id: '123' }); + }); + + it('should run the list middleware', async () => { + const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); + + const { marks } = await run('/middlewares-list'); + + expect(marks).toEqual([ + 'before:m-root', + 'before:m-list-a', + 'before:m-list-b', + 'before:m-list-c', + 'list', + 'after:m-list-c', + 'after:m-list-b', + 'after:m-list-a', + 'after:m-root' + ]); + }); + + it('should run the list of middlewares and route with middlewares list', async () => { + const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); + + const { marks } = await run('/middlewares-list/route-with-middlewares'); + + expect(marks).toEqual([ + 'before:m-root', + 'before:m-list-a', + 'before:m-list-b', + 'before:m-list-c', + 'before:a', + 'before:b', + 'before:c', + 'route-with-middlewares', + 'after:c', + 'after:b', + 'after:a', + 'after:m-list-c', + 'after:m-list-b', + 'after:m-list-a', + 'after:m-root' + ]); + }); + + it('should handle single item in the array as route handler with route params', async () => { + const run = createTestRequestRunner(middlewaresRequestHandler); + const { routeParams } = await run('/middlewares-list/123/single-route'); + expect(routeParams?.id).toEqual('123'); + }); + + it('should handle nested single item in the array as route handler with route params', async () => { + const run = createTestRequestRunner(middlewaresRequestHandler); + + const { routeParams } = await run('/middlewares-list/123/nested/456'); + + expect(routeParams?.id).toEqual('123'); + expect(routeParams?.nestedId).toEqual('456'); + }); + + it('should get route params in middlewares', async () => { + const run = createTestRequestRunner(middlewaresRequestHandler); + const { routeParams } = await run('/nested/7/unreachable'); + expect(routeParams?.id).toEqual('7'); + }); + + it('should interrupt middleware chain', async () => { + const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); + + const { marks, result } = await run('/interruption/unreachable-route'); + + expect(result).toEqual('before:interrupted'); + expect(marks).toEqual([ + 'before:m-root', + 'before:md-interruption', + 'after:m-root' + ]); + }); + + it('should interrupt the call chain of a file route before next', async () => { + const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); + + const { marks, result } = await run('/interruption-in-list'); + + expect(result).toEqual('before:interrupted'); + expect(marks).toEqual([ + 'before:m-root', + 'before:a', + 'before:b-interruption', + 'after:a', + 'after:m-root' + ]); + }); + + it('should interrupt the call chain in the root middleware', async () => { + const requestHandler = await initFileRouter({ + baseDir: 'api-middlewares/interruption' + }); + const run = createTestMiddlewareRequestRunner(requestHandler); + + const { marks, result } = await run('/unreachable-route'); + + expect(result).toEqual('before:interrupted'); + expect(marks).toEqual(['before:md-interruption']); + }); + + it('should interrupt the call chain in the root file handler', async () => { + const requestHandler = await initFileRouter({ + baseDir: 'api-middlewares/interruption-in-list' + }); + const run = createTestMiddlewareRequestRunner(requestHandler); + + const { marks, result } = await run('/'); + + expect(result).toEqual('before:interrupted'); + expect(marks).toEqual(['before:a', 'before:b-interruption', 'after:a']); + }); + + it('should catch and handle error of the file route', async () => { + const requestHandler = await initFileRouter({ + baseDir: 'api-middlewares/error-handler/in-file-route' + }); + + const run = createTestMiddlewareRequestRunner(requestHandler); + const { marks } = await run('/'); + + expect(marks).toEqual(['before:root', 'list', 'handled-error:root']); + }); + + it('should catch and handle error of middlewares file', async () => { + const requestHandler = await initFileRouter({ + baseDir: 'api-middlewares/error-handler/in-middleware' + }); + + const run = createTestMiddlewareRequestRunner(requestHandler); + const { marks } = await run('/unreachable-route'); + + expect(marks).toEqual([ + 'before:a', + 'before:b', + 'before:c', + 'handled-error:a' + ]); + }); + + it('should be able to pass data through pipelines', async () => { + const requestHandler = await initFileRouter({ + baseDir: 'api-middlewares/next-fn-result' + }); + + const run = createTestMiddlewareRequestRunner(requestHandler); + const { result } = await run('/in-middle'); + + expect(result).toEqual('some-data'); + }); + + it('should use the last returned data in the pipeline', async () => { + const requestHandler = await initFileRouter({ + baseDir: 'api-middlewares/next-fn-result' + }); + + const run = createTestMiddlewareRequestRunner(requestHandler); + const { result } = await run('/override'); + + expect(result).toEqual('new-data'); + }); + }); +}); diff --git a/tests/request-handler-classes.test.ts b/tests/request-handler-classes.test.ts new file mode 100644 index 0000000..ffbc110 --- /dev/null +++ b/tests/request-handler-classes.test.ts @@ -0,0 +1,50 @@ +import { createTestRequestRunner } from './test-utils'; +import { initFileRouter } from '../src'; +import { afterEach, describe, expect, it, vi } from 'vitest'; + +const currentCwd = process.cwd(); +vi.mock('process', () => ({ + cwd: () => `${currentCwd}/tests` +})); + +describe('RequestHandler', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('#Classes', () => { + const baseDir = `${process.cwd()}/tests/api-classes`; + + it('should invoke http-method based handlers from class-based file', async () => { + const requestHandler = await initFileRouter({ baseDir }); + const run = createTestRequestRunner(requestHandler); + + await run('/3/endpoint', 'post').then(({ req, routeParams }) => { + expect(routeParams).toEqual({ id: '3' }); + expect(req?.method).toBe('post'); + }); + await run('/3/endpoint', 'get').then(({ req, routeParams }) => { + expect(routeParams).toEqual({ id: '3' }); + expect(req?.method).toBe('get'); + }); + }); + + it('should invoke http-method based handlers from instance of class based file', async () => { + const requestHandler = await initFileRouter({ baseDir }); + const run = createTestRequestRunner(requestHandler); + + await run('/3/endpoint-with-instance', 'post').then( + ({ req, routeParams }) => { + expect(routeParams).toEqual({ id: '3' }); + expect(req?.method).toBe('post'); + } + ); + await run('/3/endpoint-with-instance', 'get').then( + ({ req, routeParams }) => { + expect(routeParams).toEqual({ id: '3' }); + expect(req?.method).toBe('get'); + } + ); + }); + }); +}); diff --git a/tests/request-handler.test.ts b/tests/request-handler.test.ts index fe5cdab..9f2436b 100644 --- a/tests/request-handler.test.ts +++ b/tests/request-handler.test.ts @@ -1,8 +1,4 @@ -import { - createTestMiddlewareRequestRunner, - createTestRequestRunner, - expectAfterInit -} from './test-utils'; +import { createTestRequestRunner, expectAfterInit } from './test-utils'; import { initFileRouter } from '../src'; import { afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; import type { FileRouterRequestHandler } from '../src'; @@ -19,27 +15,6 @@ describe('RequestHandler', () => { vi.clearAllMocks(); }); - describe('#Initialization', () => { - it('should init file router with the default params', async () => { - const requestHandler = await initFileRouter(); - - const run = createTestRequestRunner(requestHandler); - const { filePath } = await run('/'); - - expect(filePath).toBe('/api/index.ts'); - }); - - it('should init file router with an absolute path', async () => { - const baseDir = `${process.cwd()}/tests/api`; - const requestHandler = await initFileRouter({ baseDir }); - const run = createTestRequestRunner(requestHandler); - - const { filePath } = await run('/'); - - expect(filePath).toBe('/api/index.ts'); - }); - }); - describe('#Adapter', () => { const adapter = { getPathname: (req: IncomingMessage) => req.url || '', @@ -453,234 +428,4 @@ describe('RequestHandler', () => { ); }); }); - - describe('#Middlewares', () => { - let middlewaresRequestHandler: FileRouterRequestHandler; - - beforeAll(async () => { - middlewaresRequestHandler = await initFileRouter({ - baseDir: 'api-middlewares' - }); - }); - - it('should run the root middleware', async () => { - const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); - - const { marks } = await run('/'); - - expect(marks).toEqual(['before:m-root', 'root-index', 'after:m-root']); - }); - - it('should run the root middleware for dynamic route', async () => { - const runForMiddleware = createTestMiddlewareRequestRunner( - middlewaresRequestHandler - ); - const runForRoute = createTestRequestRunner(middlewaresRequestHandler); - - const { marks } = await runForMiddleware('/nested/123'); - expect(marks).toEqual(['before:m-root', '[id]', 'after:m-root']); - const { routeParams } = await runForRoute('/nested/123'); - expect(routeParams).toEqual({ id: '123' }); - }); - - it('should run the list middleware', async () => { - const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); - - const { marks } = await run('/middlewares-list'); - - expect(marks).toEqual([ - 'before:m-root', - 'before:m-list-a', - 'before:m-list-b', - 'before:m-list-c', - 'list', - 'after:m-list-c', - 'after:m-list-b', - 'after:m-list-a', - 'after:m-root' - ]); - }); - - it('should run the list of middlewares and route with middlewares list', async () => { - const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); - - const { marks } = await run('/middlewares-list/route-with-middlewares'); - - expect(marks).toEqual([ - 'before:m-root', - 'before:m-list-a', - 'before:m-list-b', - 'before:m-list-c', - 'before:a', - 'before:b', - 'before:c', - 'route-with-middlewares', - 'after:c', - 'after:b', - 'after:a', - 'after:m-list-c', - 'after:m-list-b', - 'after:m-list-a', - 'after:m-root' - ]); - }); - - it('should handle single item in the array as route handler with route params', async () => { - const run = createTestRequestRunner(middlewaresRequestHandler); - const { routeParams } = await run('/middlewares-list/123/single-route'); - expect(routeParams?.id).toEqual('123'); - }); - - it('should handle nested single item in the array as route handler with route params', async () => { - const run = createTestRequestRunner(middlewaresRequestHandler); - - const { routeParams } = await run('/middlewares-list/123/nested/456'); - - expect(routeParams?.id).toEqual('123'); - expect(routeParams?.nestedId).toEqual('456'); - }); - - it('should get route params in middlewares', async () => { - const run = createTestRequestRunner(middlewaresRequestHandler); - const { routeParams } = await run('/nested/7/unreachable'); - expect(routeParams?.id).toEqual('7'); - }); - - it('should interrupt middleware chain', async () => { - const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); - - const { marks, result } = await run('/interruption/unreachable-route'); - - expect(result).toEqual('before:interrupted'); - expect(marks).toEqual([ - 'before:m-root', - 'before:md-interruption', - 'after:m-root' - ]); - }); - - it('should interrupt the call chain of a file route before next', async () => { - const run = createTestMiddlewareRequestRunner(middlewaresRequestHandler); - - const { marks, result } = await run('/interruption-in-list'); - - expect(result).toEqual('before:interrupted'); - expect(marks).toEqual([ - 'before:m-root', - 'before:a', - 'before:b-interruption', - 'after:a', - 'after:m-root' - ]); - }); - - it('should interrupt the call chain in the root middleware', async () => { - const requestHandler = await initFileRouter({ - baseDir: 'api-middlewares/interruption' - }); - const run = createTestMiddlewareRequestRunner(requestHandler); - - const { marks, result } = await run('/unreachable-route'); - - expect(result).toEqual('before:interrupted'); - expect(marks).toEqual(['before:md-interruption']); - }); - - it('should interrupt the call chain in the root file handler', async () => { - const requestHandler = await initFileRouter({ - baseDir: 'api-middlewares/interruption-in-list' - }); - const run = createTestMiddlewareRequestRunner(requestHandler); - - const { marks, result } = await run('/'); - - expect(result).toEqual('before:interrupted'); - expect(marks).toEqual(['before:a', 'before:b-interruption', 'after:a']); - }); - - it('should catch and handle error of the file route', async () => { - const requestHandler = await initFileRouter({ - baseDir: 'api-middlewares/error-handler/in-file-route' - }); - - const run = createTestMiddlewareRequestRunner(requestHandler); - const { marks } = await run('/'); - - expect(marks).toEqual(['before:root', 'list', 'handled-error:root']); - }); - - it('should catch and handle error of middlewares file', async () => { - const requestHandler = await initFileRouter({ - baseDir: 'api-middlewares/error-handler/in-middleware' - }); - - const run = createTestMiddlewareRequestRunner(requestHandler); - const { marks } = await run('/unreachable-route'); - - expect(marks).toEqual([ - 'before:a', - 'before:b', - 'before:c', - 'handled-error:a' - ]); - }); - - it('should be able to pass data through pipelines', async () => { - const requestHandler = await initFileRouter({ - baseDir: 'api-middlewares/next-fn-result' - }); - - const run = createTestMiddlewareRequestRunner(requestHandler); - const { result } = await run('/in-middle'); - - expect(result).toEqual('some-data'); - }); - - it('should use the last returned data in the pipeline', async () => { - const requestHandler = await initFileRouter({ - baseDir: 'api-middlewares/next-fn-result' - }); - - const run = createTestMiddlewareRequestRunner(requestHandler); - const { result } = await run('/override'); - - expect(result).toEqual('new-data'); - }); - }); - - describe('#Classes', () => { - const baseDir = `${process.cwd()}/tests/api-classes`; - - it('should invoke http-method based handlers from class-based file', async () => { - const requestHandler = await initFileRouter({ baseDir }); - const run = createTestRequestRunner(requestHandler); - - await run('/3/endpoint', 'post').then(({ req, routeParams }) => { - expect(routeParams).toEqual({ id: '3' }); - expect(req?.method).toBe('post'); - }); - await run('/3/endpoint', 'get').then(({ req, routeParams }) => { - expect(routeParams).toEqual({ id: '3' }); - expect(req?.method).toBe('get'); - }); - }); - - it('should invoke http-method based handlers from instance of class based file', async () => { - const requestHandler = await initFileRouter({ baseDir }); - const run = createTestRequestRunner(requestHandler); - - await run('/3/endpoint-with-instance', 'post').then( - ({ req, routeParams }) => { - expect(routeParams).toEqual({ id: '3' }); - expect(req?.method).toBe('post'); - } - ); - await run('/3/endpoint-with-instance', 'get').then( - ({ req, routeParams }) => { - expect(routeParams).toEqual({ id: '3' }); - expect(req?.method).toBe('get'); - } - ); - }); - }); }); diff --git a/website/docs/usage-guide.mdx b/website/docs/usage-guide.mdx index dd8dd26..300fd3a 100644 --- a/website/docs/usage-guide.mdx +++ b/website/docs/usage-guide.mdx @@ -249,3 +249,48 @@ export default function(req, res, routeParams) { // ... your code } ``` + +## Get All Registered Routes + +Get all parsed routes for cases where you need to show or process all routes after initialization. +The initialization function `initFileRouter` receives lifecycle callback `onInit` which has `routes`. + +```ts +await initFileRouter({ + onInit: ({ routes }) => { + console.log({ routes }) + } +}); +``` + +The list contains the following items: +```ts +interface Route { + // Formatted endpoint path + // Example: "shops/[shopId]/products/[productId]" + urlPath: string; + + // Contains the request handler functions from the file + // For instance, + // - for single handler: + // (req, res, routeParams) => {} + // - for method-based handler: + // { + // get: (req, res, routeParams) => {}, + // post: (req, res, routeParams) => {} + // } + handler: RequestHandler | Record; + + // When a file has a specified method in its name, like suppliers.[get].ts + // Example: 'get', 'post', 'put', etc. + method?: string; + + // The filename + // Example: suppliers.[get].ts + fileName: string; + + // Regexp which is used to match URL on file + // Example: ^\/one\/(?[^/]+)\/two\/(?[^/]+)\/?$ + regex: RegExp; +} +``` diff --git a/website/package.json b/website/package.json index 3b59e5a..f683665 100644 --- a/website/package.json +++ b/website/package.json @@ -17,7 +17,7 @@ "dependencies": { "@docusaurus/core": "3.7.0", "@docusaurus/preset-classic": "3.7.0", - "@mdx-js/react": "3.0.1", + "@mdx-js/react": "3.1.0", "clsx": "2.1.0", "prism-react-renderer": "2.4.1", "react": "18.3.1", diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index f4d77bd..acf865c 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -10,13 +10,13 @@ importers: dependencies: '@docusaurus/core': specifier: 3.7.0 - version: 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + version: 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/preset-classic': specifier: 3.7.0 - version: 3.7.0(@algolia/client-search@5.20.0)(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0)(typescript@5.2.2) + version: 3.7.0(@algolia/client-search@5.20.0)(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0)(typescript@5.2.2) '@mdx-js/react': - specifier: 3.0.1 - version: 3.0.1(@types/react@18.2.12)(react@18.3.1) + specifier: 3.1.0 + version: 3.1.0(@types/react@18.2.12)(react@18.3.1) clsx: specifier: 2.1.0 version: 2.1.0 @@ -38,7 +38,7 @@ importers: version: 2.0.3 docusaurus-plugin-sass: specifier: 0.2.6 - version: 0.2.6(@docusaurus/core@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(sass@1.66.1)(webpack@5.97.1) + version: 0.2.6(@docusaurus/core@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(sass@1.66.1)(webpack@5.97.1) typescript: specifier: 5.2.2 version: 5.2.2 @@ -1799,8 +1799,8 @@ packages: '@mdx-js/mdx@3.0.0': resolution: {integrity: sha512-Icm0TBKBLYqroYbNW3BPnzMGn+7mwpQOK310aZ7+fkCtiU3aqv2cdcX+nd0Ydo3wI5Rx8bX2Z2QmGb/XcAClCw==} - '@mdx-js/react@3.0.1': - resolution: {integrity: sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==} + '@mdx-js/react@3.1.0': + resolution: {integrity: sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==} peerDependencies: '@types/react': '>=16' react: '>=16' @@ -7722,7 +7722,7 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/core@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/core@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: '@docusaurus/babel': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/bundler': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) @@ -7731,7 +7731,7 @@ snapshots: '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-common': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mdx-js/react': 3.0.1(@types/react@18.2.12)(react@18.3.1) + '@mdx-js/react': 3.1.0(@types/react@18.2.12)(react@18.3.1) boxen: 6.2.1 chalk: 4.1.2 chokidar: 3.5.3 @@ -7871,13 +7871,13 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/plugin-content-blog@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-content-blog@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/logger': 3.7.0 '@docusaurus/mdx-loader': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-common': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -7914,13 +7914,13 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/logger': 3.7.0 '@docusaurus/mdx-loader': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/module-type-aliases': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-common': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -7955,9 +7955,9 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-content-pages@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-content-pages@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/mdx-loader': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -7987,9 +7987,9 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-debug@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-debug@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) fs-extra: 11.1.1 @@ -8017,9 +8017,9 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-analytics@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-google-analytics@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -8045,9 +8045,9 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-gtag@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-google-gtag@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/gtag.js': 0.0.12 @@ -8074,9 +8074,9 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-google-tag-manager@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-google-tag-manager@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 @@ -8102,9 +8102,9 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-sitemap@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-sitemap@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/logger': 3.7.0 '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -8135,9 +8135,9 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/plugin-svgr@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': + '@docusaurus/plugin-svgr@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -8167,21 +8167,21 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/preset-classic@3.7.0(@algolia/client-search@5.20.0)(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0)(typescript@5.2.2)': - dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-content-blog': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-content-pages': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-debug': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-google-analytics': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-google-gtag': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-google-tag-manager': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-sitemap': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-svgr': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/preset-classic@3.7.0(@algolia/client-search@5.20.0)(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0)(typescript@5.2.2)': + dependencies: + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-content-blog': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-content-pages': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-debug': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-google-analytics': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-google-gtag': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-google-tag-manager': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-sitemap': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-svgr': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/theme-classic': 3.7.0(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/theme-search-algolia': 3.7.0(@algolia/client-search@5.20.0)(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0)(typescript@5.2.2) + '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/theme-search-algolia': 3.7.0(@algolia/client-search@5.20.0)(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0)(typescript@5.2.2) '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -8221,20 +8221,20 @@ snapshots: '@docusaurus/theme-classic@3.7.0(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)': dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/logger': 3.7.0 '@docusaurus/mdx-loader': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/module-type-aliases': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-blog': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/plugin-content-pages': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/plugin-content-blog': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-content-pages': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/theme-translations': 3.7.0 '@docusaurus/types': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-common': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@mdx-js/react': 3.0.1(@types/react@18.2.12)(react@18.3.1) + '@mdx-js/react': 3.1.0(@types/react@18.2.12)(react@18.3.1) clsx: 2.1.0 copy-text-to-clipboard: 3.2.0 infima: 0.2.0-alpha.45 @@ -8269,11 +8269,11 @@ snapshots: - vue-template-compiler - webpack-cli - '@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@docusaurus/theme-common@3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@docusaurus/mdx-loader': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/module-type-aliases': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-common': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/history': 4.7.11 @@ -8293,13 +8293,13 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/theme-search-algolia@3.7.0(@algolia/client-search@5.20.0)(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0)(typescript@5.2.2)': + '@docusaurus/theme-search-algolia@3.7.0(@algolia/client-search@5.20.0)(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0)(typescript@5.2.2)': dependencies: '@docsearch/react': 3.8.3(@algolia/client-search@5.20.0)(@types/react@18.2.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.6.0) - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@docusaurus/logger': 3.7.0 - '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docusaurus/plugin-content-docs': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/theme-common': 3.7.0(@docusaurus/plugin-content-docs@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/theme-translations': 3.7.0 '@docusaurus/utils': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -8528,7 +8528,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1)': + '@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1)': dependencies: '@types/mdx': 2.0.9 '@types/react': 18.2.12 @@ -8576,7 +8576,7 @@ snapshots: '@slorber/react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@babel/runtime': 7.23.2 + '@babel/runtime': 7.26.7 invariant: 2.2.4 prop-types: 15.8.1 react: 18.3.1 @@ -9839,9 +9839,9 @@ snapshots: dependencies: '@leichtgewicht/ip-codec': 2.0.4 - docusaurus-plugin-sass@0.2.6(@docusaurus/core@3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(sass@1.66.1)(webpack@5.97.1): + docusaurus-plugin-sass@0.2.6(@docusaurus/core@3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2))(sass@1.66.1)(webpack@5.97.1): dependencies: - '@docusaurus/core': 3.7.0(@mdx-js/react@3.0.1(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) + '@docusaurus/core': 3.7.0(@mdx-js/react@3.1.0(@types/react@18.2.12)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) sass: 1.66.1 sass-loader: 16.0.4(sass@1.66.1)(webpack@5.97.1) transitivePeerDependencies: @@ -12596,7 +12596,7 @@ snapshots: dependencies: chokidar: 3.5.3 immutable: 4.3.2 - source-map-js: 1.0.2 + source-map-js: 1.2.1 sax@1.2.4: {}