From 960aa8319fc29413a6999ebb030f79ec63b8d3c3 Mon Sep 17 00:00:00 2001 From: KostyaTretyak Date: Tue, 14 Jul 2026 23:48:05 +0300 Subject: [PATCH 1/7] feat(sentry): replace RequestDispatcher with SentryRequestDispatcher and add E2E tests - Implement SentryRequestDispatcher to wrap all incoming HTTP request handling (including routing, parameter parsing, and guards execution) inside Sentry isolation scope, trace continuation, and spans. - Remove SentrySpanInterceptor as its functionality is now redundant and fully covered by SentryRequestDispatcher. - Add comprehensive E2E tests verifying trace continuation, span lifecycle, and automatic capture of uncaught exceptions. - Add Node.js subpath imports (#src/*) to the sentry package to support clean imports in E2E tests. --- packages/sentry/e2e/sentry.spec.ts | 128 ++++++++++++++++++ packages/sentry/jest.config.ts | 2 +- packages/sentry/package.json | 5 +- packages/sentry/src/index.ts | 2 +- .../src/sentry-request-dispatcher.spec.ts | 112 +++++++++++++++ .../sentry/src/sentry-request-dispatcher.ts | 55 ++++++++ .../src/sentry-span.interceptor.spec.ts | 90 ------------ .../sentry/src/sentry-span.interceptor.ts | 35 ----- packages/sentry/src/sentry.extension.spec.ts | 10 +- packages/sentry/src/sentry.extension.ts | 20 +-- packages/sentry/src/sentry.module.ts | 4 +- packages/sentry/tsconfig.json | 1 + 12 files changed, 311 insertions(+), 153 deletions(-) create mode 100644 packages/sentry/e2e/sentry.spec.ts create mode 100644 packages/sentry/src/sentry-request-dispatcher.spec.ts create mode 100644 packages/sentry/src/sentry-request-dispatcher.ts delete mode 100644 packages/sentry/src/sentry-span.interceptor.spec.ts delete mode 100644 packages/sentry/src/sentry-span.interceptor.ts diff --git a/packages/sentry/e2e/sentry.spec.ts b/packages/sentry/e2e/sentry.spec.ts new file mode 100644 index 000000000..9d85fbfee --- /dev/null +++ b/packages/sentry/e2e/sentry.spec.ts @@ -0,0 +1,128 @@ +import { jest } from '@jest/globals'; +import request from 'supertest'; +import { rootModule } from '@ditsmod/core'; +import { route, RestModule, controller, initRest, RequestDispatcher, HttpErrorHandler, restRootModule } from '@ditsmod/rest'; +import { TestRestApplication, TestRestPlugin } from '@ditsmod/rest-testing'; + +// 1. Mock Sentry before imports +const mockSpan = { + setStatus: jest.fn(), +}; + +const mockScope = { + setTag: jest.fn(), + setExtra: jest.fn(), + setTransactionName: jest.fn(), +}; + +const mockClient = { + getDsn: () => 'https://mock-public-key@mock-sentry-host/mock-project-id', +}; + +jest.unstable_mockModule('@sentry/node', async () => { + const actual = await jest.requireActual('@sentry/node'); + return { + ...actual, + init: jest.fn(), + getClient: () => mockClient, + getCurrentScope: jest.fn(() => mockScope), + getIsolationScope: jest.fn(() => mockScope), + withIsolationScope: jest.fn((callback: any) => callback()), + continueTrace: jest.fn((options: any, callback: any) => callback()), + startSpan: jest.fn((options: any, callback: any) => callback(mockSpan)), + captureException: jest.fn(), + }; +}); + +jest.unstable_mockModule('@sentry/core', async () => { + const actual = await jest.requireActual('@sentry/core'); + return { + ...actual, + getClient: jest.fn(() => mockClient), + getIsolationScope: jest.fn(() => mockScope), + }; +}); + +// 2. Import modules after Sentry mock +const Sentry = (await import('@sentry/node')) as any; +const { SentryModule } = await import('#src/index.js'); + +@controller() +class HelloController { + @route('GET', 'hello') + tellHello() { + return 'hello'; + } + + @route('GET', 'throw-error') + throwErr() { + throw new Error('test-error'); + } +} + +@restRootModule({ + imports: [RestModule, SentryModule], + controllers: [HelloController], + resolvedCollisionPerRou: [[HttpErrorHandler, SentryModule]], + resolvedCollisionPerApp: [[RequestDispatcher, SentryModule]], +}) +class AppModule {} + +describe('Sentry E2E Tests', () => { + let server: any; + + beforeEach(async () => { + jest.clearAllMocks(); + }); + + afterAll(() => { + if (server) { + server.close(); + } + }); + + it('should process standard request, trace it, and update transaction name', async () => { + server = await TestRestApplication.createTestApp(AppModule).$use(TestRestPlugin).getServer(); + + const response = await request(server) + .get('/hello') + .set('sentry-trace', 'trace-id-123') + .set('baggage', 'baggage-data-123'); + + expect(response.status).toBe(200); + expect(response.text).toBe('hello'); + + // Verify Sentry request listener wrapping occurred + expect(Sentry.withIsolationScope).toHaveBeenCalled(); + expect(Sentry.continueTrace).toHaveBeenCalledWith( + { + sentryTrace: 'trace-id-123', + baggage: 'baggage-data-123', + }, + expect.any(Function), + ); + expect(Sentry.startSpan).toHaveBeenCalledWith( + { + name: 'GET /hello', + op: 'http.server', + }, + expect.any(Function), + ); + + // Verify SentryTracingInterceptor updated the transaction name to parametrized name + expect(mockScope.setTransactionName).toHaveBeenCalledWith('GET /hello'); + expect(mockSpan.setStatus).toHaveBeenCalledWith({ code: 1 }); + }); + + it('should capture unhandled exceptions and set span status to error', async () => { + server = await TestRestApplication.createTestApp(AppModule).$use(TestRestPlugin).getServer(); + + const response = await request(server).get('/throw-error'); + + expect(response.status).toBe(500); + + // Verify that exception is captured and span is marked as error + expect(Sentry.captureException).toHaveBeenCalledWith(expect.any(Error), expect.any(Object)); + expect(mockSpan.setStatus).toHaveBeenCalledWith({ code: 2, message: 'HTTP 500' }); + }); +}); diff --git a/packages/sentry/jest.config.ts b/packages/sentry/jest.config.ts index 14844197d..d784c3ea5 100644 --- a/packages/sentry/jest.config.ts +++ b/packages/sentry/jest.config.ts @@ -2,7 +2,7 @@ import type { Config } from 'jest'; const config: Config = { testEnvironment: 'node', - modulePathIgnorePatterns: ['/src/'], + modulePathIgnorePatterns: ['/src/', '/e2e/'], setupFilesAfterEnv: ['reflect-metadata/lite'], }; diff --git a/packages/sentry/package.json b/packages/sentry/package.json index d6c5dfd2b..0b449ed17 100644 --- a/packages/sentry/package.json +++ b/packages/sentry/package.json @@ -18,10 +18,13 @@ "default": "./dist/index.js" } }, + "imports": { + "#src/*": "./dist/*" + }, "scripts": { "build": "tsc -b tsconfig.build.json", "clean": "rm -rf dist*", - "test": "tsc -b tsconfig.unit.json && yarn esm-jest", + "test": "tsc -b tsconfig.e2e.json && yarn esm-jest", "esm-jest": "yarn node --experimental-vm-modules --no-warnings=ExperimentalWarning --enable-source-maps $(yarn bin jest)" }, "keywords": [ diff --git a/packages/sentry/src/index.ts b/packages/sentry/src/index.ts index 4a672d254..4f7e2fad8 100644 --- a/packages/sentry/src/index.ts +++ b/packages/sentry/src/index.ts @@ -1,8 +1,8 @@ export { SentryHttpErrorHandler } from './sentry.http-error-handler.js'; export { SentryModule } from './sentry.module.js'; export { SentryTracingInterceptor } from './sentry-tracing.interceptor.js'; -export { SentrySpanInterceptor } from './sentry-span.interceptor.js'; export { SentryExtension } from './sentry.extension.js'; export { SentryRouteMeta, SentryOptions } from './types.js'; export { sentryCron, sentryTraced, sentryExceptionCaptured, isExpectedError } from './decorators.js'; export { init, getDefaultIntegrations } from './sdk.js'; +export { SentryRequestDispatcher } from './sentry-request-dispatcher.js'; diff --git a/packages/sentry/src/sentry-request-dispatcher.spec.ts b/packages/sentry/src/sentry-request-dispatcher.spec.ts new file mode 100644 index 000000000..9cb0425d5 --- /dev/null +++ b/packages/sentry/src/sentry-request-dispatcher.spec.ts @@ -0,0 +1,112 @@ +import { jest } from '@jest/globals'; +import { Logger, Injector } from '@ditsmod/core'; + +// Mock Sentry +const mockSpan = { + setStatus: jest.fn(), +}; + +jest.unstable_mockModule('@sentry/node', () => { + return { + withIsolationScope: jest.fn((callback: any) => callback()), + continueTrace: jest.fn((options: any, callback: any) => callback()), + startSpan: jest.fn((options: any, callback: any) => callback(mockSpan)), + captureException: jest.fn(), + }; +}); + +// Dynamically import code under test +const { SentryRequestDispatcher } = await import('./sentry-request-dispatcher.js'); +const Sentry = (await import('@sentry/node')) as any; +const { Router } = await import('@ditsmod/rest'); +const { SystemLogMediator } = await import('@ditsmod/core'); + +describe('SentryRequestDispatcher', () => { + let dispatcher: any; + let mockRouter: any; + let mockSystemLogMediator: any; + let mockLogger: any; + + beforeEach(() => { + jest.clearAllMocks(); + + mockRouter = { + find: jest.fn(() => ({ handle: jest.fn(() => Promise.resolve()), params: [] })), + }; + + mockLogger = { + log: jest.fn(), + }; + + mockSystemLogMediator = { + internalServerError: jest.fn(), + }; + + const injector = Injector.resolveAndCreate([ + { token: Router, useValue: mockRouter }, + { token: Logger, useValue: mockLogger }, + { token: SystemLogMediator, useValue: mockSystemLogMediator }, + SentryRequestDispatcher, + ]); + + dispatcher = injector.get(SentryRequestDispatcher); + }); + + it('should wrap requestListener with isolation scope, continueTrace and startSpan', async () => { + const rawReq = { + method: 'GET', + url: '/users/123?foo=bar', + headers: { + 'sentry-trace': 'trace-id', + baggage: 'baggage-data', + }, + }; + const rawRes = { + statusCode: 200, + end: jest.fn(), + }; + + await dispatcher.requestListener(rawReq, rawRes); + + expect(Sentry.withIsolationScope).toHaveBeenCalled(); + expect(Sentry.continueTrace).toHaveBeenCalledWith( + { + sentryTrace: 'trace-id', + baggage: 'baggage-data', + }, + expect.any(Function), + ); + expect(Sentry.startSpan).toHaveBeenCalledWith( + { + name: 'GET /users/123', + op: 'http.server', + }, + expect.any(Function), + ); + expect(mockSpan.setStatus).toHaveBeenCalledWith({ code: 1 }); + }); + + it('should capture exception and throw when handler throws error', async () => { + const rawReq = { + method: 'GET', + url: '/users/123', + headers: {}, + }; + const rawRes = { + statusCode: 500, + end: jest.fn(), + }; + + const error = new Error('Database connection failed'); + mockRouter.find.mockReturnValue({ + handle: jest.fn(() => Promise.reject(error)), + params: [], + }); + + await dispatcher.requestListener(rawReq, rawRes); + + expect(Sentry.captureException).toHaveBeenCalledWith(error); + expect(mockSpan.setStatus).toHaveBeenCalledWith({ code: 2, message: 'HTTP 500' }); + expect(rawRes.end).toHaveBeenCalled(); + }); +}); diff --git a/packages/sentry/src/sentry-request-dispatcher.ts b/packages/sentry/src/sentry-request-dispatcher.ts new file mode 100644 index 000000000..2c2cdfdc6 --- /dev/null +++ b/packages/sentry/src/sentry-request-dispatcher.ts @@ -0,0 +1,55 @@ +import * as Sentry from '@sentry/node'; +import { injectable, SystemLogMediator } from '@ditsmod/core'; +import { RequestDispatcher, Router } from '@ditsmod/rest'; +import type { RawResponse } from '@ditsmod/rest'; + +@injectable() +export class SentryRequestDispatcher extends RequestDispatcher { + constructor(router: Router, systemLogMediator: SystemLogMediator) { + super(router, systemLogMediator); + const originalRequestListener = this.requestListener; + + this.requestListener = async (rawReq, rawRes) => { + return Sentry.withIsolationScope(async () => { + const traceHeaders = rawReq.headers['sentry-trace']; + const baggage = rawReq.headers['baggage']; + + return Sentry.continueTrace( + { + sentryTrace: traceHeaders as string, + baggage: baggage as string, + }, + () => { + const [pathname] = (rawReq.url || '').split('?'); + return Sentry.startSpan( + { + name: `${rawReq.method} ${pathname}`, + op: 'http.server', + }, + async (span) => { + try { + await originalRequestListener(rawReq, rawRes); + } catch (err) { + Sentry.captureException(err); + throw err; + } finally { + const statusCode = rawRes.statusCode; + if (statusCode >= 400) { + span?.setStatus({ code: 2, message: `HTTP ${statusCode}` }); + } else { + span?.setStatus({ code: 1 }); + } + } + }, + ); + }, + ); + }); + }; + } + + override sendInternalServerError(rawRes: RawResponse, err: Error) { + Sentry.captureException(err); + super.sendInternalServerError(rawRes, err); + } +} diff --git a/packages/sentry/src/sentry-span.interceptor.spec.ts b/packages/sentry/src/sentry-span.interceptor.spec.ts deleted file mode 100644 index 0ef166107..000000000 --- a/packages/sentry/src/sentry-span.interceptor.spec.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { jest } from '@jest/globals'; - -const mockSpan = { - setStatus: jest.fn(), -}; - -jest.unstable_mockModule('@sentry/node', () => { - return { - withIsolationScope: jest.fn((callback: any) => callback()), - startSpan: jest.fn((options: any, callback: any) => callback(mockSpan)), - }; -}); - -import type { HttpHandler, BaseRequestContext } from '@ditsmod/rest'; - -// Import dynamically after mock -const Sentry = (await import('@sentry/node')) as any; -const { SentrySpanInterceptor } = await import('./sentry-span.interceptor.js'); - -describe('SentrySpanInterceptor', () => { - let interceptor: any; - let next: HttpHandler; - let ctx: BaseRequestContext; - - beforeEach(() => { - jest.clearAllMocks(); - - next = { - handle: jest.fn(() => Promise.resolve('ok')), - }; - - ctx = { - rawReq: { - method: 'GET', - url: '/users', - }, - } as any; - }); - - it('should start Sentry span with path from RouteMeta', async () => { - const routeMeta = { - fullPath: 'users/:id', - } as any; - - interceptor = new SentrySpanInterceptor(routeMeta); - await interceptor.intercept(next, ctx); - - expect(Sentry.withIsolationScope).toHaveBeenCalled(); - expect(Sentry.startSpan).toHaveBeenCalledWith( - { - name: 'GET /users/:id', - op: 'http.server', - attributes: { - 'http.method': 'GET', - 'http.route': '/users/:id', - }, - }, - expect.any(Function), - ); - expect(next.handle).toHaveBeenCalled(); - }); - - it('should fallback to ctx.rawReq.url if RouteMeta is missing', async () => { - interceptor = new SentrySpanInterceptor(undefined); - await interceptor.intercept(next, ctx); - - expect(Sentry.withIsolationScope).toHaveBeenCalled(); - expect(Sentry.startSpan).toHaveBeenCalledWith( - { - name: 'GET /users', - op: 'http.server', - attributes: { - 'http.method': 'GET', - 'http.route': '/users', - }, - }, - expect.any(Function), - ); - }); - - it('should set span status to error if handle throws', async () => { - const err = new Error('database failure'); - next.handle = jest.fn(() => Promise.reject(err)); - - interceptor = new SentrySpanInterceptor(undefined); - await expect(interceptor.intercept(next, ctx)).rejects.toThrow(err); - - expect(mockSpan.setStatus).toHaveBeenCalledWith({ code: 2, message: 'database failure' }); - }); -}); diff --git a/packages/sentry/src/sentry-span.interceptor.ts b/packages/sentry/src/sentry-span.interceptor.ts deleted file mode 100644 index 7223d8f48..000000000 --- a/packages/sentry/src/sentry-span.interceptor.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as Sentry from '@sentry/node'; - -import { injectable, optional } from '@ditsmod/core'; -import type { HttpInterceptor, HttpHandler, BaseRequestContext } from '@ditsmod/rest'; - -import type { SentryRouteMeta } from './types.js'; - -@injectable() -export class SentrySpanInterceptor implements HttpInterceptor { - constructor(@optional() private routeMeta?: SentryRouteMeta) {} - - async intercept(next: HttpHandler, ctx: BaseRequestContext): Promise { - const method = (ctx.rawReq.method ?? 'GET').toUpperCase(); - const path = this.routeMeta ? `/${this.routeMeta.fullPath ?? ctx.rawReq.url}` : (ctx.rawReq.url ?? '/'); - - return Sentry.withIsolationScope(() => { - return Sentry.startSpan( - { - name: `${method} ${path}`, - op: 'http.server', - attributes: { - 'http.method': method, - 'http.route': path, - }, - }, - (span) => { - return next.handle().catch((err) => { - span?.setStatus({ code: 2, message: (err as Error).message }); - throw err; - }); - }, - ); - }); - } -} diff --git a/packages/sentry/src/sentry.extension.spec.ts b/packages/sentry/src/sentry.extension.spec.ts index eddd1d26e..46f8aa2a7 100644 --- a/packages/sentry/src/sentry.extension.spec.ts +++ b/packages/sentry/src/sentry.extension.spec.ts @@ -17,7 +17,6 @@ jest.unstable_mockModule('@sentry/core', async () => { // Import dynamically after mock const { SentryExtension } = await import('./sentry.extension.js'); -const { SentrySpanInterceptor } = await import('./sentry-span.interceptor.js'); const { SentryTracingInterceptor } = await import('./sentry-tracing.interceptor.js'); describe('SentryExtension', () => { @@ -35,7 +34,7 @@ describe('SentryExtension', () => { extension = new SentryExtension(extensionManager, logger); }); - it('should push tracing and span interceptors to providersPerReq of all controllers', async () => { + it('should push tracing interceptor to providersPerReq of all controllers', async () => { const mockControllerMetadata = { providersPerReq: [] as any[], routeMeta: {} as any, @@ -51,13 +50,6 @@ describe('SentryExtension', () => { await extension.stage1(); - expect(mockControllerMetadata.providersPerReq).toContain(SentrySpanInterceptor); - expect(mockControllerMetadata.providersPerReq).toContainEqual({ - token: HTTP_INTERCEPTORS, - useToken: SentrySpanInterceptor, - multi: true, - }); - expect(mockControllerMetadata.providersPerReq).toContain(SentryTracingInterceptor); expect(mockControllerMetadata.providersPerReq).toContainEqual({ token: HTTP_INTERCEPTORS, diff --git a/packages/sentry/src/sentry.extension.ts b/packages/sentry/src/sentry.extension.ts index 03dbbf9f9..c0dba9160 100644 --- a/packages/sentry/src/sentry.extension.ts +++ b/packages/sentry/src/sentry.extension.ts @@ -4,7 +4,6 @@ import { injectable, Logger, ExtensionManager } from '@ditsmod/core'; import type { Extension } from '@ditsmod/core'; import { RestRouteExtension, HTTP_INTERCEPTORS } from '@ditsmod/rest'; -import { SentrySpanInterceptor } from './sentry-span.interceptor.js'; import { SentryTracingInterceptor } from './sentry-tracing.interceptor.js'; import type { SentryRouteMeta } from './types.js'; @@ -31,20 +30,11 @@ export class SentryExtension implements Extension { // Dynamically append the fullPath to routeMeta (controllerMetadata.routeMeta as SentryRouteMeta).fullPath = controllerMetadata.fullPath; - controllerMetadata.providersPerReq.push( - SentrySpanInterceptor, - { - token: HTTP_INTERCEPTORS, - useToken: SentrySpanInterceptor, - multi: true, - }, - SentryTracingInterceptor, - { - token: HTTP_INTERCEPTORS, - useToken: SentryTracingInterceptor, - multi: true, - }, - ); + controllerMetadata.providersPerReq.push(SentryTracingInterceptor, { + token: HTTP_INTERCEPTORS, + useToken: SentryTracingInterceptor, + multi: true, + }); } } } diff --git a/packages/sentry/src/sentry.module.ts b/packages/sentry/src/sentry.module.ts index 179a0f9a9..beeeff6eb 100644 --- a/packages/sentry/src/sentry.module.ts +++ b/packages/sentry/src/sentry.module.ts @@ -1,10 +1,12 @@ import { featureModule } from '@ditsmod/core'; -import { HttpErrorHandler, RestRouteExtension, DispatcherExtension } from '@ditsmod/rest'; +import { HttpErrorHandler, RestRouteExtension, DispatcherExtension, RequestDispatcher } from '@ditsmod/rest'; import { SentryHttpErrorHandler } from './sentry.http-error-handler.js'; import { SentryExtension } from './sentry.extension.js'; +import { SentryRequestDispatcher } from './sentry-request-dispatcher.js'; @featureModule({ + providersPerApp: [SentryRequestDispatcher, { token: RequestDispatcher, useToken: SentryRequestDispatcher }], providersPerRou: [SentryHttpErrorHandler, { token: HttpErrorHandler, useToken: SentryHttpErrorHandler }], exports: [SentryHttpErrorHandler, HttpErrorHandler], extensions: [ diff --git a/packages/sentry/tsconfig.json b/packages/sentry/tsconfig.json index 2f3fce6d0..2a9e291c1 100644 --- a/packages/sentry/tsconfig.json +++ b/packages/sentry/tsconfig.json @@ -5,6 +5,7 @@ "paths": { "@ditsmod/core": ["../core/src/index.js"], "@ditsmod/rest": ["../rest/src/index.js"], + "#src/*": ["./src/*"] }, "module": "nodenext", "moduleResolution": "nodenext", From 639c25e6deb019f05e807c048bd0da3d8808c3eb Mon Sep 17 00:00:00 2001 From: KostyaTretyak Date: Wed, 15 Jul 2026 00:06:56 +0300 Subject: [PATCH 2/7] chore(ci): add rule for AI --- AGENTS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 32bfabb8e..f3131e3cb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -75,3 +75,8 @@ Run `yarn docs-en` to preview changes locally. ## User Interaction - If the user asks a question, do not modify any code immediately. It is sufficient to answer the question first. Only modify the code when the user explicitly instructs to do so. + +## Usability Feedback Loop + +- **Confusing Behavior Tracking**: When agents receive a new task to modify code or write tests (especially E2E tests), they must maintain a dedicated, fresh scope for that specific task to track "what exactly in the framework confused them". +- **Post-Task Report**: Upon completing the task, agents must explicitly report in a separate section of their final response for that task whether all framework behaviors were expected, and list anything that was confusing or unintuitive. From fca18f22bc791000e3de5d89dd66c20642c2c02f Mon Sep 17 00:00:00 2001 From: KostyaTretyak Date: Wed, 15 Jul 2026 01:10:31 +0300 Subject: [PATCH 3/7] chore(website): add `@docusaurus/theme-mermaid` --- website/docusaurus.config.js | 4 + website/package.json | 1 + website/yarn.lock | 1035 +++++++++++++++++++++++++++++++++- 3 files changed, 1032 insertions(+), 8 deletions(-) diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index dde135875..1602bcb23 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -12,6 +12,10 @@ module.exports = { organizationName: 'ditsmod', // Usually your GitHub org/user name. projectName: 'ditsmod.github.io', // Usually your repo name. trailingSlash: true, + markdown: { + mermaid: true, + }, + themes: ['@docusaurus/theme-mermaid'], themeConfig: { navbar: { // title: 'Головна', diff --git a/website/package.json b/website/package.json index a09b6553b..31bf6b6cb 100644 --- a/website/package.json +++ b/website/package.json @@ -17,6 +17,7 @@ "@docusaurus/core": "^3.10.2", "@docusaurus/plugin-client-redirects": "^3.10.2", "@docusaurus/preset-classic": "^3.10.2", + "@docusaurus/theme-mermaid": "^3.10.2", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", "prism-react-renderer": "^2.3.0", diff --git a/website/yarn.lock b/website/yarn.lock index a881fbed7..fcaee506b 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -250,6 +250,16 @@ __metadata: languageName: node linkType: hard +"@antfu/install-pkg@npm:^1.1.0": + version: 1.1.0 + resolution: "@antfu/install-pkg@npm:1.1.0" + dependencies: + package-manager-detector: "npm:^1.3.0" + tinyexec: "npm:^1.0.1" + checksum: 10c0/140d5994c76fd3d0e824c88f1ce91b3370e8066a8bc2f5729ae133bf768caa239f7915e29c78f239b7ead253113ace51293e95127fafe2b786b88eb615b3be47 + languageName: node + linkType: hard + "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.2": version: 7.24.2 resolution: "@babel/code-frame@npm:7.24.2" @@ -3025,6 +3035,20 @@ __metadata: languageName: node linkType: hard +"@braintree/sanitize-url@npm:^7.1.2": + version: 7.1.2 + resolution: "@braintree/sanitize-url@npm:7.1.2" + checksum: 10c0/62f2aa0cf58626e3880b2dc1025c42064b4639abd157ae4e1c35f4c2f5031e9273772046a423979845069c814e27ff818e8e669280dc53585e6f033d5b7a59cb + languageName: node + linkType: hard + +"@chevrotain/types@npm:~11.1.2": + version: 11.1.2 + resolution: "@chevrotain/types@npm:11.1.2" + checksum: 10c0/c0c4679a3d407df34e18d5adfa7ac599b4a2bfddbf68da6e43678b9b3e16ab911de7766b37b9fc466261c3dead3db1b620e2e344f800fa9f0f381720475eda8f + languageName: node + linkType: hard + "@colors/colors@npm:1.5.0": version: 1.5.0 resolution: "@colors/colors@npm:1.5.0" @@ -4088,6 +4112,28 @@ __metadata: languageName: node linkType: hard +"@docusaurus/theme-mermaid@npm:^3.10.2": + version: 3.10.2 + resolution: "@docusaurus/theme-mermaid@npm:3.10.2" + dependencies: + "@docusaurus/core": "npm:3.10.2" + "@docusaurus/module-type-aliases": "npm:3.10.2" + "@docusaurus/theme-common": "npm:3.10.2" + "@docusaurus/types": "npm:3.10.2" + "@docusaurus/utils-validation": "npm:3.10.2" + mermaid: "npm:>=11.6.0" + tslib: "npm:^2.6.0" + peerDependencies: + "@mermaid-js/layout-elk": ^0.1.9 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@mermaid-js/layout-elk": + optional: true + checksum: 10c0/5a1c783d8b7a188c119cd2d0167d70099a6d6121f001f8cca68cdbc167b9606b9d2cc6da59b005b1edcefbff06ee2e5547247cc0d8d01d33abd99dee35bb3903 + languageName: node + linkType: hard + "@docusaurus/theme-search-algolia@npm:3.10.2": version: 3.10.2 resolution: "@docusaurus/theme-search-algolia@npm:3.10.2" @@ -4218,6 +4264,24 @@ __metadata: languageName: node linkType: hard +"@iconify/types@npm:^2.0.0": + version: 2.0.0 + resolution: "@iconify/types@npm:2.0.0" + checksum: 10c0/65a3be43500c7ccacf360e136d00e1717f050b7b91da644e94370256ac66f582d59212bdb30d00788aab4fc078262e91c95b805d1808d654b72f6d2072a7e4b2 + languageName: node + linkType: hard + +"@iconify/utils@npm:^3.0.2": + version: 3.1.4 + resolution: "@iconify/utils@npm:3.1.4" + dependencies: + "@antfu/install-pkg": "npm:^1.1.0" + "@iconify/types": "npm:^2.0.0" + import-meta-resolve: "npm:^4.2.0" + checksum: 10c0/2176311415d5853e0e19056a833014324d0a98989936945fbcc4fb4b0ae92178f6ed13c9b4c8e1200191991b78af421b7dd49cc03b474c7a824696d73033e1c1 + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -4434,6 +4498,15 @@ __metadata: languageName: node linkType: hard +"@mermaid-js/parser@npm:^1.2.0": + version: 1.2.0 + resolution: "@mermaid-js/parser@npm:1.2.0" + dependencies: + "@chevrotain/types": "npm:~11.1.2" + checksum: 10c0/907d41167b23160c88f292b0dd79162d2543445ecf1d784ed09747467705666669f818e3ab91e1182da2127720fb40cb707e6fd56e8a445020fd3e7b8b16f013 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -4798,6 +4871,278 @@ __metadata: languageName: node linkType: hard +"@types/d3-array@npm:*": + version: 3.2.2 + resolution: "@types/d3-array@npm:3.2.2" + checksum: 10c0/6137cb97302f8a4f18ca22c0560c585cfcb823f276b23d89f2c0c005d72697ec13bca671c08e68b4b0cabd622e3f0e91782ee221580d6774074050be96dd7028 + languageName: node + linkType: hard + +"@types/d3-axis@npm:*": + version: 3.0.6 + resolution: "@types/d3-axis@npm:3.0.6" + dependencies: + "@types/d3-selection": "npm:*" + checksum: 10c0/d756d42360261f44d8eefd0950c5bb0a4f67a46dd92069da3f723ac36a1e8cb2b9ce6347d836ef19d5b8aef725dbcf8fdbbd6cfbff676ca4b0642df2f78b599a + languageName: node + linkType: hard + +"@types/d3-brush@npm:*": + version: 3.0.6 + resolution: "@types/d3-brush@npm:3.0.6" + dependencies: + "@types/d3-selection": "npm:*" + checksum: 10c0/fd6e2ac7657a354f269f6b9c58451ffae9d01b89ccb1eb6367fd36d635d2f1990967215ab498e0c0679ff269429c57fad6a2958b68f4d45bc9f81d81672edc01 + languageName: node + linkType: hard + +"@types/d3-chord@npm:*": + version: 3.0.6 + resolution: "@types/d3-chord@npm:3.0.6" + checksum: 10c0/c5a25eb5389db01e63faec0c5c2ec7cc41c494e9b3201630b494c4e862a60f1aa83fabbc33a829e7e1403941e3c30d206c741559b14406ac2a4239cfdf4b4c17 + languageName: node + linkType: hard + +"@types/d3-color@npm:*": + version: 3.1.3 + resolution: "@types/d3-color@npm:3.1.3" + checksum: 10c0/65eb0487de606eb5ad81735a9a5b3142d30bc5ea801ed9b14b77cb14c9b909f718c059f13af341264ee189acf171508053342142bdf99338667cea26a2d8d6ae + languageName: node + linkType: hard + +"@types/d3-contour@npm:*": + version: 3.0.6 + resolution: "@types/d3-contour@npm:3.0.6" + dependencies: + "@types/d3-array": "npm:*" + "@types/geojson": "npm:*" + checksum: 10c0/e7d83e94719af4576ceb5ac7f277c5806f83ba6c3631744ae391cffc3641f09dfa279470b83053cd0b2acd6784e8749c71141d05bdffa63ca58ffb5b31a0f27c + languageName: node + linkType: hard + +"@types/d3-delaunay@npm:*": + version: 6.0.4 + resolution: "@types/d3-delaunay@npm:6.0.4" + checksum: 10c0/d154a8864f08c4ea23ecb9bdabcef1c406a25baa8895f0cb08a0ed2799de0d360e597552532ce7086ff0cdffa8f3563f9109d18f0191459d32bb620a36939123 + languageName: node + linkType: hard + +"@types/d3-dispatch@npm:*": + version: 3.0.7 + resolution: "@types/d3-dispatch@npm:3.0.7" + checksum: 10c0/38c6605ebf0bf0099dfb70eafe0dd4ae8213368b40b8f930b72a909ff2e7259d2bd8a54d100bb5a44eb4b36f4f2a62dcb37f8be59613ca6b507c7a2f910b3145 + languageName: node + linkType: hard + +"@types/d3-drag@npm:*": + version: 3.0.7 + resolution: "@types/d3-drag@npm:3.0.7" + dependencies: + "@types/d3-selection": "npm:*" + checksum: 10c0/65e29fa32a87c72d26c44b5e2df3bf15af21cd128386bcc05bcacca255927c0397d0cd7e6062aed5f0abd623490544a9d061c195f5ed9f018fe0b698d99c079d + languageName: node + linkType: hard + +"@types/d3-dsv@npm:*": + version: 3.0.7 + resolution: "@types/d3-dsv@npm:3.0.7" + checksum: 10c0/c0f01da862465594c8a28278b51c850af3b4239cc22b14fd1a19d7a98f93d94efa477bf59d8071beb285dca45bf614630811451e18e7c52add3a0abfee0a1871 + languageName: node + linkType: hard + +"@types/d3-ease@npm:*": + version: 3.0.2 + resolution: "@types/d3-ease@npm:3.0.2" + checksum: 10c0/aff5a1e572a937ee9bff6465225d7ba27d5e0c976bd9eacdac2e6f10700a7cb0c9ea2597aff6b43a6ed850a3210030870238894a77ec73e309b4a9d0333f099c + languageName: node + linkType: hard + +"@types/d3-fetch@npm:*": + version: 3.0.7 + resolution: "@types/d3-fetch@npm:3.0.7" + dependencies: + "@types/d3-dsv": "npm:*" + checksum: 10c0/3d147efa52a26da1a5d40d4d73e6cebaaa964463c378068062999b93ea3731b27cc429104c21ecbba98c6090e58ef13429db6399238c5e3500162fb3015697a0 + languageName: node + linkType: hard + +"@types/d3-force@npm:*": + version: 3.0.10 + resolution: "@types/d3-force@npm:3.0.10" + checksum: 10c0/c82b459079a106b50e346c9b79b141f599f2fc4f598985a5211e72c7a2e20d35bd5dc6e91f306b323c8bfa325c02c629b1645f5243f1c6a55bd51bc85cccfa92 + languageName: node + linkType: hard + +"@types/d3-format@npm:*": + version: 3.0.4 + resolution: "@types/d3-format@npm:3.0.4" + checksum: 10c0/3ac1600bf9061a59a228998f7cd3f29e85cbf522997671ba18d4d84d10a2a1aff4f95aceb143fa9960501c3ec351e113fc75884e6a504ace44dc1744083035ee + languageName: node + linkType: hard + +"@types/d3-geo@npm:*": + version: 3.1.0 + resolution: "@types/d3-geo@npm:3.1.0" + dependencies: + "@types/geojson": "npm:*" + checksum: 10c0/3745a93439038bb5b0b38facf435f7079812921d46406f5d38deaee59e90084ff742443c7ea0a8446df81a0d81eaf622fe7068cf4117a544bd4aa3b2dc182f88 + languageName: node + linkType: hard + +"@types/d3-hierarchy@npm:*": + version: 3.1.7 + resolution: "@types/d3-hierarchy@npm:3.1.7" + checksum: 10c0/873711737d6b8e7b6f1dda0bcd21294a48f75024909ae510c5d2c21fad2e72032e0958def4d9f68319d3aaac298ad09c49807f8bfc87a145a82693b5208613c7 + languageName: node + linkType: hard + +"@types/d3-interpolate@npm:*": + version: 3.0.4 + resolution: "@types/d3-interpolate@npm:3.0.4" + dependencies: + "@types/d3-color": "npm:*" + checksum: 10c0/066ebb8da570b518dd332df6b12ae3b1eaa0a7f4f0c702e3c57f812cf529cc3500ec2aac8dc094f31897790346c6b1ebd8cd7a077176727f4860c2b181a65ca4 + languageName: node + linkType: hard + +"@types/d3-path@npm:*": + version: 3.1.1 + resolution: "@types/d3-path@npm:3.1.1" + checksum: 10c0/2c36eb31ebaf2ce4712e793fd88087117976f7c4ed69cc2431825f999c8c77cca5cea286f3326432b770739ac6ccd5d04d851eb65e7a4dbcc10c982b49ad2c02 + languageName: node + linkType: hard + +"@types/d3-polygon@npm:*": + version: 3.0.2 + resolution: "@types/d3-polygon@npm:3.0.2" + checksum: 10c0/f46307bb32b6c2aef8c7624500e0f9b518de8f227ccc10170b869dc43e4c542560f6c8d62e9f087fac45e198d6e4b623e579c0422e34c85baf56717456d3f439 + languageName: node + linkType: hard + +"@types/d3-quadtree@npm:*": + version: 3.0.6 + resolution: "@types/d3-quadtree@npm:3.0.6" + checksum: 10c0/7eaa0a4d404adc856971c9285e1c4ab17e9135ea669d847d6db7e0066126a28ac751864e7ce99c65d526e130f56754a2e437a1617877098b3bdcc3ef23a23616 + languageName: node + linkType: hard + +"@types/d3-random@npm:*": + version: 3.0.4 + resolution: "@types/d3-random@npm:3.0.4" + checksum: 10c0/7661fe7c5071ea8a35b31a5532816a693b5e887d7635954c1ee214ac3dba727061a46b58401f862e404d1c0122c62810317ddde5bcec89f13106cb022b9d3f09 + languageName: node + linkType: hard + +"@types/d3-scale-chromatic@npm:*": + version: 3.1.0 + resolution: "@types/d3-scale-chromatic@npm:3.1.0" + checksum: 10c0/93c564e02d2e97a048e18fe8054e4a935335da6ab75a56c3df197beaa87e69122eef0dfbeb7794d4a444a00e52e3123514ee27cec084bd21f6425b7037828cc2 + languageName: node + linkType: hard + +"@types/d3-scale@npm:*": + version: 4.0.9 + resolution: "@types/d3-scale@npm:4.0.9" + dependencies: + "@types/d3-time": "npm:*" + checksum: 10c0/4ac44233c05cd50b65b33ecb35d99fdf07566bcdbc55bc1306b2f27d1c5134d8c560d356f2c8e76b096e9125ffb8d26d95f78d56e210d1c542cb255bdf31d6c8 + languageName: node + linkType: hard + +"@types/d3-selection@npm:*": + version: 3.0.11 + resolution: "@types/d3-selection@npm:3.0.11" + checksum: 10c0/0c512956c7503ff5def4bb32e0c568cc757b9a2cc400a104fc0f4cfe5e56d83ebde2a97821b6f2cb26a7148079d3b86a2f28e11d68324ed311cf35c2ed980d1d + languageName: node + linkType: hard + +"@types/d3-shape@npm:*": + version: 3.1.8 + resolution: "@types/d3-shape@npm:3.1.8" + dependencies: + "@types/d3-path": "npm:*" + checksum: 10c0/49ec2172b9eb66fc1d036e2a23966216bb972e9af51ddbed134df24bd71aedf207bb1ef81903a119eb4e1f5e927cf44beacaf64c9af86474e5548594b102b574 + languageName: node + linkType: hard + +"@types/d3-time-format@npm:*": + version: 4.0.3 + resolution: "@types/d3-time-format@npm:4.0.3" + checksum: 10c0/9ef5e8e2b96b94799b821eed5d61a3d432c7903247966d8ad951b8ce5797fe46554b425cb7888fa5bf604b4663c369d7628c0328ffe80892156671c58d1a7f90 + languageName: node + linkType: hard + +"@types/d3-time@npm:*": + version: 3.0.4 + resolution: "@types/d3-time@npm:3.0.4" + checksum: 10c0/6d9e2255d63f7a313a543113920c612e957d70da4fb0890931da6c2459010291b8b1f95e149a538500c1c99e7e6c89ffcce5554dd29a31ff134a38ea94b6d174 + languageName: node + linkType: hard + +"@types/d3-timer@npm:*": + version: 3.0.2 + resolution: "@types/d3-timer@npm:3.0.2" + checksum: 10c0/c644dd9571fcc62b1aa12c03bcad40571553020feeb5811f1d8a937ac1e65b8a04b759b4873aef610e28b8714ac71c9885a4d6c127a048d95118f7e5b506d9e1 + languageName: node + linkType: hard + +"@types/d3-transition@npm:*": + version: 3.0.9 + resolution: "@types/d3-transition@npm:3.0.9" + dependencies: + "@types/d3-selection": "npm:*" + checksum: 10c0/4f68b9df7ac745b3491216c54203cbbfa0f117ae4c60e2609cdef2db963582152035407fdff995b10ee383bae2f05b7743493f48e1b8e46df54faa836a8fb7b5 + languageName: node + linkType: hard + +"@types/d3-zoom@npm:*": + version: 3.0.8 + resolution: "@types/d3-zoom@npm:3.0.8" + dependencies: + "@types/d3-interpolate": "npm:*" + "@types/d3-selection": "npm:*" + checksum: 10c0/1dbdbcafddcae12efb5beb6948546963f29599e18bc7f2a91fb69cc617c2299a65354f2d47e282dfb86fec0968406cd4fb7f76ba2d2fb67baa8e8d146eb4a547 + languageName: node + linkType: hard + +"@types/d3@npm:^7.4.3": + version: 7.4.3 + resolution: "@types/d3@npm:7.4.3" + dependencies: + "@types/d3-array": "npm:*" + "@types/d3-axis": "npm:*" + "@types/d3-brush": "npm:*" + "@types/d3-chord": "npm:*" + "@types/d3-color": "npm:*" + "@types/d3-contour": "npm:*" + "@types/d3-delaunay": "npm:*" + "@types/d3-dispatch": "npm:*" + "@types/d3-drag": "npm:*" + "@types/d3-dsv": "npm:*" + "@types/d3-ease": "npm:*" + "@types/d3-fetch": "npm:*" + "@types/d3-force": "npm:*" + "@types/d3-format": "npm:*" + "@types/d3-geo": "npm:*" + "@types/d3-hierarchy": "npm:*" + "@types/d3-interpolate": "npm:*" + "@types/d3-path": "npm:*" + "@types/d3-polygon": "npm:*" + "@types/d3-quadtree": "npm:*" + "@types/d3-random": "npm:*" + "@types/d3-scale": "npm:*" + "@types/d3-scale-chromatic": "npm:*" + "@types/d3-selection": "npm:*" + "@types/d3-shape": "npm:*" + "@types/d3-time": "npm:*" + "@types/d3-time-format": "npm:*" + "@types/d3-timer": "npm:*" + "@types/d3-transition": "npm:*" + "@types/d3-zoom": "npm:*" + checksum: 10c0/a9c6d65b13ef3b42c87f2a89ea63a6d5640221869f97d0657b0cb2f1dac96a0f164bf5605643c0794e0de3aa2bf05df198519aaf15d24ca135eb0e8bd8a9d879 + languageName: node + linkType: hard + "@types/debug@npm:^4.0.0": version: 4.1.12 resolution: "@types/debug@npm:4.1.12" @@ -4898,6 +5243,13 @@ __metadata: languageName: node linkType: hard +"@types/geojson@npm:*": + version: 7946.0.16 + resolution: "@types/geojson@npm:7946.0.16" + checksum: 10c0/1ff24a288bd5860b766b073ead337d31d73bdc715e5b50a2cee5cb0af57a1ed02cc04ef295f5fa68dc40fe3e4f104dd31282b2b818a5ba3231bc1001ba084e3c + languageName: node + linkType: hard + "@types/hast@npm:^3.0.0": version: 3.0.4 resolution: "@types/hast@npm:3.0.4" @@ -5174,6 +5526,13 @@ __metadata: languageName: node linkType: hard +"@types/trusted-types@npm:^2.0.7": + version: 2.0.7 + resolution: "@types/trusted-types@npm:2.0.7" + checksum: 10c0/4c4855f10de7c6c135e0d32ce462419d8abbbc33713b31d294596c0cc34ae1fa6112a2f9da729c8f7a20707782b0d69da3b1f8df6645b0366d08825ca1522e0c + languageName: node + linkType: hard + "@types/unist@npm:*, @types/unist@npm:^3.0.0": version: 3.0.2 resolution: "@types/unist@npm:3.0.2" @@ -5220,6 +5579,21 @@ __metadata: languageName: node linkType: hard +"@upsetjs/venn.js@npm:^2.0.0": + version: 2.0.0 + resolution: "@upsetjs/venn.js@npm:2.0.0" + dependencies: + d3-selection: "npm:^3.0.0" + d3-transition: "npm:^3.0.1" + dependenciesMeta: + d3-selection: + optional: true + d3-transition: + optional: true + checksum: 10c0/b12014d94708ab4df7f5a4b6205c6f23ff235cca2ffe91df3314862b109b826e52f9020c2a2f7527d3712d21c578d6db9cdb60ce46a528739cc18e58d111f724 + languageName: node + linkType: hard + "@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1": version: 1.12.1 resolution: "@webassemblyjs/ast@npm:1.12.1" @@ -6380,6 +6754,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:7, commander@npm:^7.2.0": + version: 7.2.0 + resolution: "commander@npm:7.2.0" + checksum: 10c0/8d690ff13b0356df7e0ebbe6c59b4712f754f4b724d4f473d3cc5b3fdcf978e3a5dc3078717858a2ceb50b0f84d0660a7f22a96cdc50fb877d0c9bb31593d23a + languageName: node + linkType: hard + "commander@npm:^10.0.0": version: 10.0.1 resolution: "commander@npm:10.0.1" @@ -6401,13 +6782,6 @@ __metadata: languageName: node linkType: hard -"commander@npm:^7.2.0": - version: 7.2.0 - resolution: "commander@npm:7.2.0" - checksum: 10c0/8d690ff13b0356df7e0ebbe6c59b4712f754f4b724d4f473d3cc5b3fdcf978e3a5dc3078717858a2ceb50b0f84d0660a7f22a96cdc50fb877d0c9bb31593d23a - languageName: node - linkType: hard - "commander@npm:^8.3.0": version: 8.3.0 resolution: "commander@npm:8.3.0" @@ -6589,6 +6963,24 @@ __metadata: languageName: node linkType: hard +"cose-base@npm:^1.0.0": + version: 1.0.3 + resolution: "cose-base@npm:1.0.3" + dependencies: + layout-base: "npm:^1.0.0" + checksum: 10c0/a6e400b1d101393d6af0967c1353355777c1106c40417c5acaef6ca8bdda41e2fc9398f466d6c85be30290943ad631f2590569f67b3fd5368a0d8318946bd24f + languageName: node + linkType: hard + +"cose-base@npm:^2.2.0": + version: 2.2.0 + resolution: "cose-base@npm:2.2.0" + dependencies: + layout-base: "npm:^2.0.0" + checksum: 10c0/14b9f8100ac322a00777ffb1daeb3321af368bbc9cabe3103943361273baee2003202ffe38e4ab770960b600214224e9c196195a78d589521540aa694df7cdec + languageName: node + linkType: hard + "cosmiconfig@npm:^8.1.3, cosmiconfig@npm:^8.3.5": version: 8.3.6 resolution: "cosmiconfig@npm:8.3.6" @@ -6895,6 +7287,405 @@ __metadata: languageName: node linkType: hard +"cytoscape-cose-bilkent@npm:^4.1.0": + version: 4.1.0 + resolution: "cytoscape-cose-bilkent@npm:4.1.0" + dependencies: + cose-base: "npm:^1.0.0" + peerDependencies: + cytoscape: ^3.2.0 + checksum: 10c0/5e2480ddba9da1a68e700ed2c674cbfd51e9efdbd55788f1971a68de4eb30708e3b3a5e808bf5628f7a258680406bbe6586d87a9133e02a9bdc1ab1a92f512f2 + languageName: node + linkType: hard + +"cytoscape-fcose@npm:^2.2.0": + version: 2.2.0 + resolution: "cytoscape-fcose@npm:2.2.0" + dependencies: + cose-base: "npm:^2.2.0" + peerDependencies: + cytoscape: ^3.2.0 + checksum: 10c0/ce472c9f85b9057e75c5685396f8e1f2468895e71b184913e05ad56dcf3092618fe59a1054f29cb0995051ba8ebe566ad0dd49a58d62845145624bd60cd44917 + languageName: node + linkType: hard + +"cytoscape@npm:^3.33.3": + version: 3.34.0 + resolution: "cytoscape@npm:3.34.0" + checksum: 10c0/cb17b3dcacb9492f058cff653debf7b5a713e7532a9866cc72ae79d207757e8a9b68430874fe986f2a6404a8161b4fb5c1a2f1ca9ac5b1a21e316f57ed9d1243 + languageName: node + linkType: hard + +"d3-array@npm:1 - 2": + version: 2.12.1 + resolution: "d3-array@npm:2.12.1" + dependencies: + internmap: "npm:^1.0.0" + checksum: 10c0/7eca10427a9f113a4ca6a0f7301127cab26043fd5e362631ef5a0edd1c4b2dd70c56ed317566700c31e4a6d88b55f3951aaba192291817f243b730cb2352882e + languageName: node + linkType: hard + +"d3-array@npm:2 - 3, d3-array@npm:2.10.0 - 3, d3-array@npm:2.5.0 - 3, d3-array@npm:3, d3-array@npm:^3.2.0": + version: 3.2.4 + resolution: "d3-array@npm:3.2.4" + dependencies: + internmap: "npm:1 - 2" + checksum: 10c0/08b95e91130f98c1375db0e0af718f4371ccacef7d5d257727fe74f79a24383e79aba280b9ffae655483ffbbad4fd1dec4ade0119d88c4749f388641c8bf8c50 + languageName: node + linkType: hard + +"d3-axis@npm:3": + version: 3.0.0 + resolution: "d3-axis@npm:3.0.0" + checksum: 10c0/a271e70ba1966daa5aaf6a7f959ceca3e12997b43297e757c7b945db2e1ead3c6ee226f2abcfa22abbd4e2e28bd2b71a0911794c4e5b911bbba271328a582c78 + languageName: node + linkType: hard + +"d3-brush@npm:3": + version: 3.0.0 + resolution: "d3-brush@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-drag: "npm:2 - 3" + d3-interpolate: "npm:1 - 3" + d3-selection: "npm:3" + d3-transition: "npm:3" + checksum: 10c0/07baf00334c576da2f68a91fc0da5732c3a5fa19bd3d7aed7fd24d1d674a773f71a93e9687c154176f7246946194d77c48c2d8fed757f5dcb1a4740067ec50a8 + languageName: node + linkType: hard + +"d3-chord@npm:3": + version: 3.0.1 + resolution: "d3-chord@npm:3.0.1" + dependencies: + d3-path: "npm:1 - 3" + checksum: 10c0/baa6013914af3f4fe1521f0d16de31a38eb8a71d08ff1dec4741f6f45a828661e5cd3935e39bd14e3032bdc78206c283ca37411da21d46ec3cfc520be6e7a7ce + languageName: node + linkType: hard + +"d3-color@npm:1 - 3, d3-color@npm:3": + version: 3.1.0 + resolution: "d3-color@npm:3.1.0" + checksum: 10c0/a4e20e1115fa696fce041fbe13fbc80dc4c19150fa72027a7c128ade980bc0eeeba4bcf28c9e21f0bce0e0dbfe7ca5869ef67746541dcfda053e4802ad19783c + languageName: node + linkType: hard + +"d3-contour@npm:4": + version: 4.0.2 + resolution: "d3-contour@npm:4.0.2" + dependencies: + d3-array: "npm:^3.2.0" + checksum: 10c0/98bc5fbed6009e08707434a952076f39f1cd6ed8b9288253cc3e6a3286e4e80c63c62d84954b20e64bf6e4ededcc69add54d3db25e990784a59c04edd3449032 + languageName: node + linkType: hard + +"d3-delaunay@npm:6": + version: 6.0.4 + resolution: "d3-delaunay@npm:6.0.4" + dependencies: + delaunator: "npm:5" + checksum: 10c0/57c3aecd2525664b07c4c292aa11cf49b2752c0cf3f5257f752999399fe3c592de2d418644d79df1f255471eec8057a9cc0c3062ed7128cb3348c45f69597754 + languageName: node + linkType: hard + +"d3-dispatch@npm:1 - 3, d3-dispatch@npm:3": + version: 3.0.1 + resolution: "d3-dispatch@npm:3.0.1" + checksum: 10c0/6eca77008ce2dc33380e45d4410c67d150941df7ab45b91d116dbe6d0a3092c0f6ac184dd4602c796dc9e790222bad3ff7142025f5fd22694efe088d1d941753 + languageName: node + linkType: hard + +"d3-drag@npm:2 - 3, d3-drag@npm:3": + version: 3.0.0 + resolution: "d3-drag@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-selection: "npm:3" + checksum: 10c0/d2556e8dc720741a443b595a30af403dd60642dfd938d44d6e9bfc4c71a962142f9a028c56b61f8b4790b65a34acad177d1263d66f103c3c527767b0926ef5aa + languageName: node + linkType: hard + +"d3-dsv@npm:1 - 3, d3-dsv@npm:3": + version: 3.0.1 + resolution: "d3-dsv@npm:3.0.1" + dependencies: + commander: "npm:7" + iconv-lite: "npm:0.6" + rw: "npm:1" + bin: + csv2json: bin/dsv2json.js + csv2tsv: bin/dsv2dsv.js + dsv2dsv: bin/dsv2dsv.js + dsv2json: bin/dsv2json.js + json2csv: bin/json2dsv.js + json2dsv: bin/json2dsv.js + json2tsv: bin/json2dsv.js + tsv2csv: bin/dsv2dsv.js + tsv2json: bin/dsv2json.js + checksum: 10c0/10e6af9e331950ed258f34ab49ac1b7060128ef81dcf32afc790bd1f7e8c3cc2aac7f5f875250a83f21f39bb5925fbd0872bb209f8aca32b3b77d32bab8a65ab + languageName: node + linkType: hard + +"d3-ease@npm:1 - 3, d3-ease@npm:3": + version: 3.0.1 + resolution: "d3-ease@npm:3.0.1" + checksum: 10c0/fec8ef826c0cc35cda3092c6841e07672868b1839fcaf556e19266a3a37e6bc7977d8298c0fcb9885e7799bfdcef7db1baaba9cd4dcf4bc5e952cf78574a88b0 + languageName: node + linkType: hard + +"d3-fetch@npm:3": + version: 3.0.1 + resolution: "d3-fetch@npm:3.0.1" + dependencies: + d3-dsv: "npm:1 - 3" + checksum: 10c0/4f467a79bf290395ac0cbb5f7562483f6a18668adc4c8eb84c9d3eff048b6f6d3b6f55079ba1ebf1908dabe000c941d46be447f8d78453b2dad5fb59fb6aa93b + languageName: node + linkType: hard + +"d3-force@npm:3": + version: 3.0.0 + resolution: "d3-force@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-quadtree: "npm:1 - 3" + d3-timer: "npm:1 - 3" + checksum: 10c0/220a16a1a1ac62ba56df61028896e4b52be89c81040d20229c876efc8852191482c233f8a52bb5a4e0875c321b8e5cb6413ef3dfa4d8fe79eeb7d52c587f52cf + languageName: node + linkType: hard + +"d3-format@npm:1 - 3, d3-format@npm:3": + version: 3.1.2 + resolution: "d3-format@npm:3.1.2" + checksum: 10c0/0de452ae07585238e7f01607a7e0066665c34609652188b6ac7dc9f424f69465a425e07d16d79bd0e5955202ac7f241c66d0c76f68a79fc6f4857c94cf420652 + languageName: node + linkType: hard + +"d3-geo@npm:3": + version: 3.1.1 + resolution: "d3-geo@npm:3.1.1" + dependencies: + d3-array: "npm:2.5.0 - 3" + checksum: 10c0/d32270dd2dc8ac3ea63e8805d63239c4c8ec6c0d339d73b5e5a30a87f8f54db22a78fb434369799465eae169503b25f9a107c642c8a16c32a3285bc0e6d8e8c1 + languageName: node + linkType: hard + +"d3-hierarchy@npm:3": + version: 3.1.2 + resolution: "d3-hierarchy@npm:3.1.2" + checksum: 10c0/6dcdb480539644aa7fc0d72dfc7b03f99dfbcdf02714044e8c708577e0d5981deb9d3e99bbbb2d26422b55bcc342ac89a0fa2ea6c9d7302e2fc0951dd96f89cf + languageName: node + linkType: hard + +"d3-interpolate@npm:1 - 3, d3-interpolate@npm:1.2.0 - 3, d3-interpolate@npm:3": + version: 3.0.1 + resolution: "d3-interpolate@npm:3.0.1" + dependencies: + d3-color: "npm:1 - 3" + checksum: 10c0/19f4b4daa8d733906671afff7767c19488f51a43d251f8b7f484d5d3cfc36c663f0a66c38fe91eee30f40327443d799be17169f55a293a3ba949e84e57a33e6a + languageName: node + linkType: hard + +"d3-path@npm:1": + version: 1.0.9 + resolution: "d3-path@npm:1.0.9" + checksum: 10c0/e35e84df5abc18091f585725b8235e1fa97efc287571585427d3a3597301e6c506dea56b11dfb3c06ca5858b3eb7f02c1bf4f6a716aa9eade01c41b92d497eb5 + languageName: node + linkType: hard + +"d3-path@npm:1 - 3, d3-path@npm:3, d3-path@npm:^3.1.0": + version: 3.1.0 + resolution: "d3-path@npm:3.1.0" + checksum: 10c0/dc1d58ec87fa8319bd240cf7689995111a124b141428354e9637aa83059eb12e681f77187e0ada5dedfce346f7e3d1f903467ceb41b379bfd01cd8e31721f5da + languageName: node + linkType: hard + +"d3-polygon@npm:3": + version: 3.0.1 + resolution: "d3-polygon@npm:3.0.1" + checksum: 10c0/e236aa7f33efa9a4072907af7dc119f85b150a0716759d4fe5f12f62573018264a6cbde8617fbfa6944a7ae48c1c0c8d3f39ae72e11f66dd471e9b5e668385df + languageName: node + linkType: hard + +"d3-quadtree@npm:1 - 3, d3-quadtree@npm:3": + version: 3.0.1 + resolution: "d3-quadtree@npm:3.0.1" + checksum: 10c0/18302d2548bfecaef788152397edec95a76400fd97d9d7f42a089ceb68d910f685c96579d74e3712d57477ed042b056881b47cd836a521de683c66f47ce89090 + languageName: node + linkType: hard + +"d3-random@npm:3": + version: 3.0.1 + resolution: "d3-random@npm:3.0.1" + checksum: 10c0/987a1a1bcbf26e6cf01fd89d5a265b463b2cea93560fc17d9b1c45e8ed6ff2db5924601bcceb808de24c94133f000039eb7fa1c469a7a844ccbf1170cbb25b41 + languageName: node + linkType: hard + +"d3-sankey@npm:^0.12.3": + version: 0.12.3 + resolution: "d3-sankey@npm:0.12.3" + dependencies: + d3-array: "npm:1 - 2" + d3-shape: "npm:^1.2.0" + checksum: 10c0/261debb01a13269f6fc53b9ebaef174a015d5ad646242c23995bf514498829ab8b8f920a7873724a7494288b46bea3ce7ebc5a920b745bc8ae4caa5885cf5204 + languageName: node + linkType: hard + +"d3-scale-chromatic@npm:3": + version: 3.1.0 + resolution: "d3-scale-chromatic@npm:3.1.0" + dependencies: + d3-color: "npm:1 - 3" + d3-interpolate: "npm:1 - 3" + checksum: 10c0/9a3f4671ab0b971f4a411b42180d7cf92bfe8e8584e637ce7e698d705e18d6d38efbd20ec64f60cc0dfe966c20d40fc172565bc28aaa2990c0a006360eed91af + languageName: node + linkType: hard + +"d3-scale@npm:4": + version: 4.0.2 + resolution: "d3-scale@npm:4.0.2" + dependencies: + d3-array: "npm:2.10.0 - 3" + d3-format: "npm:1 - 3" + d3-interpolate: "npm:1.2.0 - 3" + d3-time: "npm:2.1.1 - 3" + d3-time-format: "npm:2 - 4" + checksum: 10c0/65d9ad8c2641aec30ed5673a7410feb187a224d6ca8d1a520d68a7d6eac9d04caedbff4713d1e8545be33eb7fec5739983a7ab1d22d4e5ad35368c6729d362f1 + languageName: node + linkType: hard + +"d3-selection@npm:2 - 3, d3-selection@npm:3, d3-selection@npm:^3.0.0": + version: 3.0.0 + resolution: "d3-selection@npm:3.0.0" + checksum: 10c0/e59096bbe8f0cb0daa1001d9bdd6dbc93a688019abc97d1d8b37f85cd3c286a6875b22adea0931b0c88410d025563e1643019161a883c516acf50c190a11b56b + languageName: node + linkType: hard + +"d3-shape@npm:3": + version: 3.2.0 + resolution: "d3-shape@npm:3.2.0" + dependencies: + d3-path: "npm:^3.1.0" + checksum: 10c0/f1c9d1f09926daaf6f6193ae3b4c4b5521e81da7d8902d24b38694517c7f527ce3c9a77a9d3a5722ad1e3ff355860b014557b450023d66a944eabf8cfde37132 + languageName: node + linkType: hard + +"d3-shape@npm:^1.2.0": + version: 1.3.7 + resolution: "d3-shape@npm:1.3.7" + dependencies: + d3-path: "npm:1" + checksum: 10c0/548057ce59959815decb449f15632b08e2a1bdce208f9a37b5f98ec7629dda986c2356bc7582308405ce68aedae7d47b324df41507404df42afaf352907577ae + languageName: node + linkType: hard + +"d3-time-format@npm:2 - 4, d3-time-format@npm:4": + version: 4.1.0 + resolution: "d3-time-format@npm:4.1.0" + dependencies: + d3-time: "npm:1 - 3" + checksum: 10c0/735e00fb25a7fd5d418fac350018713ae394eefddb0d745fab12bbff0517f9cdb5f807c7bbe87bb6eeb06249662f8ea84fec075f7d0cd68609735b2ceb29d206 + languageName: node + linkType: hard + +"d3-time@npm:1 - 3, d3-time@npm:2.1.1 - 3, d3-time@npm:3": + version: 3.1.0 + resolution: "d3-time@npm:3.1.0" + dependencies: + d3-array: "npm:2 - 3" + checksum: 10c0/a984f77e1aaeaa182679b46fbf57eceb6ebdb5f67d7578d6f68ef933f8eeb63737c0949991618a8d29472dbf43736c7d7f17c452b2770f8c1271191cba724ca1 + languageName: node + linkType: hard + +"d3-timer@npm:1 - 3, d3-timer@npm:3": + version: 3.0.1 + resolution: "d3-timer@npm:3.0.1" + checksum: 10c0/d4c63cb4bb5461d7038aac561b097cd1c5673969b27cbdd0e87fa48d9300a538b9e6f39b4a7f0e3592ef4f963d858c8a9f0e92754db73116770856f2fc04561a + languageName: node + linkType: hard + +"d3-transition@npm:2 - 3, d3-transition@npm:3, d3-transition@npm:^3.0.1": + version: 3.0.1 + resolution: "d3-transition@npm:3.0.1" + dependencies: + d3-color: "npm:1 - 3" + d3-dispatch: "npm:1 - 3" + d3-ease: "npm:1 - 3" + d3-interpolate: "npm:1 - 3" + d3-timer: "npm:1 - 3" + peerDependencies: + d3-selection: 2 - 3 + checksum: 10c0/4e74535dda7024aa43e141635b7522bb70cf9d3dfefed975eb643b36b864762eca67f88fafc2ca798174f83ca7c8a65e892624f824b3f65b8145c6a1a88dbbad + languageName: node + linkType: hard + +"d3-zoom@npm:3": + version: 3.0.0 + resolution: "d3-zoom@npm:3.0.0" + dependencies: + d3-dispatch: "npm:1 - 3" + d3-drag: "npm:2 - 3" + d3-interpolate: "npm:1 - 3" + d3-selection: "npm:2 - 3" + d3-transition: "npm:2 - 3" + checksum: 10c0/ee2036479049e70d8c783d594c444fe00e398246048e3f11a59755cd0e21de62ece3126181b0d7a31bf37bcf32fd726f83ae7dea4495ff86ec7736ce5ad36fd3 + languageName: node + linkType: hard + +"d3@npm:^7.9.0": + version: 7.9.0 + resolution: "d3@npm:7.9.0" + dependencies: + d3-array: "npm:3" + d3-axis: "npm:3" + d3-brush: "npm:3" + d3-chord: "npm:3" + d3-color: "npm:3" + d3-contour: "npm:4" + d3-delaunay: "npm:6" + d3-dispatch: "npm:3" + d3-drag: "npm:3" + d3-dsv: "npm:3" + d3-ease: "npm:3" + d3-fetch: "npm:3" + d3-force: "npm:3" + d3-format: "npm:3" + d3-geo: "npm:3" + d3-hierarchy: "npm:3" + d3-interpolate: "npm:3" + d3-path: "npm:3" + d3-polygon: "npm:3" + d3-quadtree: "npm:3" + d3-random: "npm:3" + d3-scale: "npm:4" + d3-scale-chromatic: "npm:3" + d3-selection: "npm:3" + d3-shape: "npm:3" + d3-time: "npm:3" + d3-time-format: "npm:4" + d3-timer: "npm:3" + d3-transition: "npm:3" + d3-zoom: "npm:3" + checksum: 10c0/3dd9c08c73cfaa69c70c49e603c85e049c3904664d9c79a1a52a0f52795828a1ff23592dc9a7b2257e711d68a615472a13103c212032f38e016d609796e087e8 + languageName: node + linkType: hard + +"dagre-d3-es@npm:7.0.14": + version: 7.0.14 + resolution: "dagre-d3-es@npm:7.0.14" + dependencies: + d3: "npm:^7.9.0" + lodash-es: "npm:^4.17.21" + checksum: 10c0/0dc91fc79300eb0a4eab5a48a76c2baf3ce439c389d19e2f015729bb57dafd75e1e9a4c2880daf016e81ee45caca7b21745c13b23b6cd2a786ce84767e88323e + languageName: node + linkType: hard + +"dayjs@npm:^1.11.20": + version: 1.11.21 + resolution: "dayjs@npm:1.11.21" + checksum: 10c0/bd97dfdc4bfea3c66268635690313828b386faa040fbc1f829ff42a2bd748b72c9d9b3c8f9616ce9e61fcb78923f1461a462c969c54b1084458ae1b715898fb0 + languageName: node + linkType: hard + "debounce@npm:^1.2.1": version: 1.2.1 resolution: "debounce@npm:1.2.1" @@ -7027,6 +7818,15 @@ __metadata: languageName: node linkType: hard +"delaunator@npm:5": + version: 5.1.0 + resolution: "delaunator@npm:5.1.0" + dependencies: + robust-predicates: "npm:^3.0.2" + checksum: 10c0/6489e3598212ab8759575e30f3ac26063471846e25c779048f441f2ccefd25efb9a52275e7e8e3dcc5bf5bc5c35169cf1de27f985d359fd5a24057be88fd1817 + languageName: node + linkType: hard + "depd@npm:2.0.0": version: 2.0.0 resolution: "depd@npm:2.0.0" @@ -7100,6 +7900,7 @@ __metadata: "@docusaurus/module-type-aliases": "npm:^3.10.2" "@docusaurus/plugin-client-redirects": "npm:^3.10.2" "@docusaurus/preset-classic": "npm:^3.10.2" + "@docusaurus/theme-mermaid": "npm:^3.10.2" "@docusaurus/types": "npm:^3.10.2" "@mdx-js/react": "npm:^3.0.0" clsx: "npm:^2.0.0" @@ -7174,6 +7975,18 @@ __metadata: languageName: node linkType: hard +"dompurify@npm:^3.3.3": + version: 3.4.12 + resolution: "dompurify@npm:3.4.12" + dependencies: + "@types/trusted-types": "npm:^2.0.7" + dependenciesMeta: + "@types/trusted-types": + optional: true + checksum: 10c0/127a13817353d4e20e75a991a9022a04c3af12af7479f68e2b8bee6dbc7330a96edfb8f4ebff96f4f0f24cd43e8dbba46214131f510c3aa87a843bd8b610d0ab + languageName: node + linkType: hard + "domutils@npm:^2.5.2, domutils@npm:^2.8.0": version: 2.8.0 resolution: "domutils@npm:2.8.0" @@ -7422,6 +8235,20 @@ __metadata: languageName: node linkType: hard +"es-toolkit@npm:^1.45.1": + version: 1.49.0 + resolution: "es-toolkit@npm:1.49.0" + dependenciesMeta: + "@trivago/prettier-plugin-sort-imports@4.3.0": + unplugged: true + prettier-plugin-sort-re-exports@0.0.1: + unplugged: true + vitepress-plugin-sandpack@1.1.4: + unplugged: true + checksum: 10c0/ab0864bb0c5c494ed09043d53a74b58a0ab9df1b89b9b54bce72a63de2869152d7d65e489dc89ab671f0fea243728922c8a8f8c873f1b2a53350a23360b3e2df + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.2 resolution: "escalade@npm:3.1.2" @@ -8155,6 +8982,13 @@ __metadata: languageName: node linkType: hard +"hachure-fill@npm:^0.5.2": + version: 0.5.2 + resolution: "hachure-fill@npm:0.5.2" + checksum: 10c0/307e3b6f9f2d3c11a82099c3f71eecbb9c440c00c1f896ac1732c23e6dbff16a92bb893d222b8b721b89cf11e58649ca60b4c24e5663f705f877cefd40153429 + languageName: node + linkType: hard + "handle-thing@npm:^2.0.0": version: 2.0.1 resolution: "handle-thing@npm:2.0.1" @@ -8624,7 +9458,7 @@ __metadata: languageName: node linkType: hard -"iconv-lite@npm:^0.6.2": +"iconv-lite@npm:0.6, iconv-lite@npm:^0.6.2": version: 0.6.3 resolution: "iconv-lite@npm:0.6.3" dependencies: @@ -8675,6 +9509,13 @@ __metadata: languageName: node linkType: hard +"import-meta-resolve@npm:^4.2.0": + version: 4.2.0 + resolution: "import-meta-resolve@npm:4.2.0" + checksum: 10c0/3ee8aeecb61d19b49d2703987f977e9d1c7d4ba47db615a570eaa02fe414f40dfa63f7b953e842cbe8470d26df6371332bfcf21b2fd92b0112f9fea80dde2c4c + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -8738,6 +9579,20 @@ __metadata: languageName: node linkType: hard +"internmap@npm:1 - 2": + version: 2.0.3 + resolution: "internmap@npm:2.0.3" + checksum: 10c0/8cedd57f07bbc22501516fbfc70447f0c6812871d471096fad9ea603516eacc2137b633633daf432c029712df0baefd793686388ddf5737e3ea15074b877f7ed + languageName: node + linkType: hard + +"internmap@npm:^1.0.0": + version: 1.0.1 + resolution: "internmap@npm:1.0.1" + checksum: 10c0/60942be815ca19da643b6d4f23bd0bf4e8c97abbd080fb963fe67583b60bdfb3530448ad4486bae40810e92317bded9995cc31411218acc750d72cd4e8646eee + languageName: node + linkType: hard + "invariant@npm:^2.2.4": version: 2.2.4 resolution: "invariant@npm:2.2.4" @@ -9236,6 +10091,17 @@ __metadata: languageName: node linkType: hard +"katex@npm:^0.16.45": + version: 0.16.47 + resolution: "katex@npm:0.16.47" + dependencies: + commander: "npm:^8.3.0" + bin: + katex: cli.js + checksum: 10c0/b10f4d0651c60771a48444879e4227255e26e2b2ec061b1ee4b08934863ad2324ba8dbb772455f7768aeb14dfcc13bcd309174a0ddd5ef954a607f644a197710 + languageName: node + linkType: hard + "keyv@npm:^4.5.3": version: 4.5.4 resolution: "keyv@npm:4.5.4" @@ -9245,6 +10111,13 @@ __metadata: languageName: node linkType: hard +"khroma@npm:^2.1.0": + version: 2.1.0 + resolution: "khroma@npm:2.1.0" + checksum: 10c0/634d98753ff5d2540491cafeb708fc98de0d43f4e6795256d5c8f6e3ad77de93049ea41433928fda3697adf7bbe6fe27351858f6d23b78f8b5775ef314c59891 + languageName: node + linkType: hard + "kind-of@npm:^6.0.0, kind-of@npm:^6.0.2, kind-of@npm:^6.0.3": version: 6.0.3 resolution: "kind-of@npm:6.0.3" @@ -9278,6 +10151,20 @@ __metadata: languageName: node linkType: hard +"layout-base@npm:^1.0.0": + version: 1.0.2 + resolution: "layout-base@npm:1.0.2" + checksum: 10c0/2a55d0460fd9f6ed53d7e301b9eb3dea19bda03815d616a40665ce6dc75c1f4d62e1ca19a897da1cfaf6de1b91de59cd6f2f79ba1258f3d7fccc7d46ca7f3337 + languageName: node + linkType: hard + +"layout-base@npm:^2.0.0": + version: 2.0.1 + resolution: "layout-base@npm:2.0.1" + checksum: 10c0/a44df9ef3cbff9916a10f616635e22b5787c89fa62b2fec6f99e8e6ee512c7cebd22668ce32dab5a83c934ba0a309c51a678aa0b40d70853de6c357893c0a88b + languageName: node + linkType: hard + "leven@npm:^3.1.0": version: 3.1.0 resolution: "leven@npm:3.1.0" @@ -9326,6 +10213,13 @@ __metadata: languageName: node linkType: hard +"lodash-es@npm:^4.17.21": + version: 4.18.1 + resolution: "lodash-es@npm:4.18.1" + checksum: 10c0/35d4dcf87ef07f8d090f409447575800108057e360b445f590d0d25d09e3d1e33a163d2fc100d4d072b0f901d5e2fc533cd7c4bfd8eeb38a06abec693823c8b8 + languageName: node + linkType: hard + "lodash.debounce@npm:^4.0.8": version: 4.0.8 resolution: "lodash.debounce@npm:4.0.8" @@ -9446,6 +10340,15 @@ __metadata: languageName: node linkType: hard +"marked@npm:^16.3.0": + version: 16.4.2 + resolution: "marked@npm:16.4.2" + bin: + marked: bin/marked.js + checksum: 10c0/fc6051142172454f2023f3d6b31cca92879ec8e1b96457086a54c70354c74b00e1b6543a76a1fad6d399366f52b90a848f6ffb8e1d65a5baff87f3ba9b8f1847 + languageName: node + linkType: hard + "math-intrinsics@npm:^1.1.0": version: 1.1.0 resolution: "math-intrinsics@npm:1.1.0" @@ -9762,6 +10665,35 @@ __metadata: languageName: node linkType: hard +"mermaid@npm:>=11.6.0": + version: 11.16.0 + resolution: "mermaid@npm:11.16.0" + dependencies: + "@braintree/sanitize-url": "npm:^7.1.2" + "@iconify/utils": "npm:^3.0.2" + "@mermaid-js/parser": "npm:^1.2.0" + "@types/d3": "npm:^7.4.3" + "@upsetjs/venn.js": "npm:^2.0.0" + cytoscape: "npm:^3.33.3" + cytoscape-cose-bilkent: "npm:^4.1.0" + cytoscape-fcose: "npm:^2.2.0" + d3: "npm:^7.9.0" + d3-sankey: "npm:^0.12.3" + dagre-d3-es: "npm:7.0.14" + dayjs: "npm:^1.11.20" + dompurify: "npm:^3.3.3" + es-toolkit: "npm:^1.45.1" + katex: "npm:^0.16.45" + khroma: "npm:^2.1.0" + marked: "npm:^16.3.0" + roughjs: "npm:^4.6.6" + stylis: "npm:^4.3.6" + ts-dedent: "npm:^2.2.0" + uuid: "npm:^11.1.0 || ^12 || ^13 || ^14.0.0" + checksum: 10c0/a14f9bc9db7f1dea65b0d6c0b920236d12ad2812f2a1b11c8b39b3dfb3c22bfce39c77f6a69493203b85880d8008d345c539efe7ae6a31d3dad512833ccfb517 + languageName: node + linkType: hard + "methods@npm:~1.1.2": version: 1.1.2 resolution: "methods@npm:1.1.2" @@ -10897,6 +11829,13 @@ __metadata: languageName: node linkType: hard +"package-manager-detector@npm:^1.3.0": + version: 1.7.0 + resolution: "package-manager-detector@npm:1.7.0" + checksum: 10c0/49488e732ef854205b8c58f68f2315c5b1006169bf9b3a34ca3042c2995edf53e805ee720778f214f32bb80cf6e7cc1ac13508423e89decc691c28329ade6a7d + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -10987,6 +11926,13 @@ __metadata: languageName: node linkType: hard +"path-data-parser@npm:0.1.0, path-data-parser@npm:^0.1.0": + version: 0.1.0 + resolution: "path-data-parser@npm:0.1.0" + checksum: 10c0/ba22d54669a8bc4a3df27431fe667900685585d1196085b803d0aa4066b83e709bbf2be7c1d2b56e706b49cc698231d55947c22abbfc4843ca424bbf8c985745 + languageName: node + linkType: hard + "path-exists@npm:^5.0.0": version: 5.0.0 resolution: "path-exists@npm:5.0.0" @@ -11096,6 +12042,23 @@ __metadata: languageName: node linkType: hard +"points-on-curve@npm:0.2.0, points-on-curve@npm:^0.2.0": + version: 0.2.0 + resolution: "points-on-curve@npm:0.2.0" + checksum: 10c0/f0d92343fcc2ad1f48334633e580574c1e0e28038a756133e171e537f270d6d64203feada5ee556e36f448a1b46e0306dee07b30f589f4e3ad720f6ee38ef48c + languageName: node + linkType: hard + +"points-on-path@npm:^0.2.1": + version: 0.2.1 + resolution: "points-on-path@npm:0.2.1" + dependencies: + path-data-parser: "npm:0.1.0" + points-on-curve: "npm:0.2.0" + checksum: 10c0/a7010340f9f196976f61838e767bb7b0b7f6273ab4fb9eb37c61001fe26fbfc3fcd63c96d5e85b9a4ab579213ab366f2ddaaf60e2a9253e2b91a62db33f395ba + languageName: node + linkType: hard + "postcss-attribute-case-insensitive@npm:^7.0.1": version: 7.0.1 resolution: "postcss-attribute-case-insensitive@npm:7.0.1" @@ -12637,6 +13600,25 @@ __metadata: languageName: node linkType: hard +"robust-predicates@npm:^3.0.2": + version: 3.0.3 + resolution: "robust-predicates@npm:3.0.3" + checksum: 10c0/ae23a0318be809545f091a076818747848f144495491e24e6df5d767f2bad0a1501bbeac34e78b74681d1437ecff0585f593ebfe6c8d49a50e79c5053b962693 + languageName: node + linkType: hard + +"roughjs@npm:^4.6.6": + version: 4.6.6 + resolution: "roughjs@npm:4.6.6" + dependencies: + hachure-fill: "npm:^0.5.2" + path-data-parser: "npm:^0.1.0" + points-on-curve: "npm:^0.2.0" + points-on-path: "npm:^0.2.1" + checksum: 10c0/68c11bf4516aa014cef2fe52426a9bab237c2f500d13e1a4f13b523cb5723667bf2d92b9619325efdc5bc2a193588ff5af8d51683df17cfb8720e96fe2b92b0c + languageName: node + linkType: hard + "rtlcss@npm:^4.1.0": version: 4.1.1 resolution: "rtlcss@npm:4.1.1" @@ -12667,6 +13649,13 @@ __metadata: languageName: node linkType: hard +"rw@npm:1": + version: 1.3.3 + resolution: "rw@npm:1.3.3" + checksum: 10c0/b1e1ef37d1e79d9dc7050787866e30b6ddcb2625149276045c262c6b4d53075ddc35f387a856a8e76f0d0df59f4cd58fe24707e40797ebee66e542b840ed6a53 + languageName: node + linkType: hard + "safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": version: 5.1.2 resolution: "safe-buffer@npm:5.1.2" @@ -13367,6 +14356,13 @@ __metadata: languageName: node linkType: hard +"stylis@npm:^4.3.6": + version: 4.4.0 + resolution: "stylis@npm:4.4.0" + checksum: 10c0/259be096d90dfbfe903c8656dcb7591e52a421e577e950ef42ebd9ca02f387623a1165dd08761492fb6e92a7a562d62a53a694a10b0a2f6dcd7a0db107b4bf55 + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -13512,6 +14508,13 @@ __metadata: languageName: node linkType: hard +"tinyexec@npm:^1.0.1": + version: 1.2.4 + resolution: "tinyexec@npm:1.2.4" + checksum: 10c0/153b8db6b080194b558ff145b9cffc36b80a6e07babd644dcfbe49c807eee668c876049d28bdee90b96304476f883352f2dad91b3f86bc23832532f4363e66ff + languageName: node + linkType: hard + "tinypool@npm:^1.0.2": version: 1.1.0 resolution: "tinypool@npm:1.1.0" @@ -13572,6 +14575,13 @@ __metadata: languageName: node linkType: hard +"ts-dedent@npm:^2.2.0": + version: 2.3.0 + resolution: "ts-dedent@npm:2.3.0" + checksum: 10c0/bfc3331e0740191c0134fb526e7f01e16657e50955c9395de14703c6ef17119c91651fa044cf558dc9c1dbb0fe1b2a74e303aeebcbd5e3b31acd14f72f545a54 + languageName: node + linkType: hard + "tslib@npm:^2.0.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" @@ -13905,6 +14915,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^11.1.0 || ^12 || ^13 || ^14.0.0": + version: 14.0.1 + resolution: "uuid@npm:14.0.1" + bin: + uuid: dist-node/bin/uuid + checksum: 10c0/2d961289097cb68c37d93d1da0b5c3aafc1eb9948a455cca8d0ae53a099b2fe583b8933254a84097f700e6bac2e23033364904df0467c22551d5d9611febcaf6 + languageName: node + linkType: hard + "uuid@npm:^8.3.2": version: 8.3.2 resolution: "uuid@npm:8.3.2" From 8b57899f177e644a7eec8d015421c1a8093d5381 Mon Sep 17 00:00:00 2001 From: KostyaTretyak Date: Wed, 15 Jul 2026 01:56:40 +0300 Subject: [PATCH 4/7] chore(ci): rename file `pre-router` to `request-dispatcher` --- ...re-router.extension.ts => request-dispatcher.extension.ts} | 0 packages/rest/src/index.ts | 4 ++-- packages/rest/src/init/rest-app-initializer.ts | 2 +- packages/rest/src/init/rest.module.ts | 4 ++-- .../src/services/{pre-router.ts => request-dispatcher.ts} | 0 ...uter.extension.ts => trpc-request-dispatcher.extension.ts} | 0 packages/trpc/src/index.ts | 2 +- packages/trpc/src/init/trpc-app-initializer.ts | 2 +- .../src/services/{pre-router.ts => request-dispatcher.ts} | 0 packages/trpc/src/services/trpc-internal.service.ts | 2 +- packages/trpc/src/trpc.module.ts | 2 +- website/docs/02-rest-application/00-rest-module.md | 2 +- .../docs/02-rest-application/01-controllers-and-services.md | 2 +- website/docs/02-rest-application/02-http-interceptors.md | 2 +- .../current/02-rest-application/00-rest-module.md | 2 +- .../02-rest-application/01-controllers-and-services.md | 2 +- .../current/02-rest-application/02-http-interceptors.md | 2 +- 17 files changed, 15 insertions(+), 15 deletions(-) rename packages/rest/src/extensions/{pre-router.extension.ts => request-dispatcher.extension.ts} (100%) rename packages/rest/src/services/{pre-router.ts => request-dispatcher.ts} (100%) rename packages/trpc/src/extensions/{trpc-pre-router.extension.ts => trpc-request-dispatcher.extension.ts} (100%) rename packages/trpc/src/services/{pre-router.ts => request-dispatcher.ts} (100%) diff --git a/packages/rest/src/extensions/pre-router.extension.ts b/packages/rest/src/extensions/request-dispatcher.extension.ts similarity index 100% rename from packages/rest/src/extensions/pre-router.extension.ts rename to packages/rest/src/extensions/request-dispatcher.extension.ts diff --git a/packages/rest/src/index.ts b/packages/rest/src/index.ts index 6f012282b..8db21dd1d 100644 --- a/packages/rest/src/index.ts +++ b/packages/rest/src/index.ts @@ -17,7 +17,7 @@ export { RestShallowModuleImports, RestResolvedModuleMetadata } from '#init/type export { RestModule } from './init/rest.module.js'; export { RequestContext } from './services/request-context.js'; export { RestRouteExtension } from './extensions/rest-route.extension.js'; -export { DispatcherExtension } from './extensions/pre-router.extension.js'; +export { DispatcherExtension } from './extensions/request-dispatcher.extension.js'; export { InterceptorExtension } from './extensions/use-interceptor.extension.js'; export { initRest, restRootModule, restModule } from './decorators/rest-init-hooks-and-metadata.js'; export { RestInitMeta } from './init/rest-init-meta.js'; @@ -52,7 +52,7 @@ export { RouteScopedHttpBackend, } from '#interceptors/tokens-and-types.js'; export { guard, CanActivate, GuardItem, NormalizedGuard, ModuleScopedGuard } from '#interceptors/guard.js'; -export { RequestDispatcher } from './services/pre-router.js'; +export { RequestDispatcher } from './services/request-dispatcher.js'; export { HTTP_INTERCEPTORS, RAW_REQ, diff --git a/packages/rest/src/init/rest-app-initializer.ts b/packages/rest/src/init/rest-app-initializer.ts index 477cb8db1..448f9258e 100644 --- a/packages/rest/src/init/rest-app-initializer.ts +++ b/packages/rest/src/init/rest-app-initializer.ts @@ -1,7 +1,7 @@ import { BaseAppInitializer } from '@ditsmod/core'; import type { RequestListener } from '#services/request.js'; -import { RequestDispatcher } from '#services/pre-router.js'; +import { RequestDispatcher } from '#services/request-dispatcher.js'; import type { HttpServer } from '#types/server-options.js'; import { SERVER } from '../top/constants.js'; diff --git a/packages/rest/src/init/rest.module.ts b/packages/rest/src/init/rest.module.ts index 3dfbe13cd..ff41402d1 100644 --- a/packages/rest/src/init/rest.module.ts +++ b/packages/rest/src/init/rest.module.ts @@ -2,10 +2,10 @@ import { BaseAppOptions, Context, ContextModule, featureModule, getTokens } from import { DefaultRouter, Router } from '#services/router.js'; import { RestRouteExtension } from '#extensions/rest-route.extension.js'; -import { DispatcherExtension } from '#extensions/pre-router.extension.js'; +import { DispatcherExtension } from '#extensions/request-dispatcher.extension.js'; import { InterceptorExtension } from '#extensions/use-interceptor.extension.js'; import { AppOptions } from '#types/app-options.js'; -import { RequestDispatcher } from '#services/pre-router.js'; +import { RequestDispatcher } from '#services/request-dispatcher.js'; import { defaultProvidersPerReq } from '#providers/default-providers-per-req.js'; import { defaultProvidersPerRou } from '#providers/default-providers-per-rou.js'; import { RouteContext } from '#services/route-context.js'; diff --git a/packages/rest/src/services/pre-router.ts b/packages/rest/src/services/request-dispatcher.ts similarity index 100% rename from packages/rest/src/services/pre-router.ts rename to packages/rest/src/services/request-dispatcher.ts diff --git a/packages/trpc/src/extensions/trpc-pre-router.extension.ts b/packages/trpc/src/extensions/trpc-request-dispatcher.extension.ts similarity index 100% rename from packages/trpc/src/extensions/trpc-pre-router.extension.ts rename to packages/trpc/src/extensions/trpc-request-dispatcher.extension.ts diff --git a/packages/trpc/src/index.ts b/packages/trpc/src/index.ts index 1833395c7..2128c736b 100644 --- a/packages/trpc/src/index.ts +++ b/packages/trpc/src/index.ts @@ -8,7 +8,7 @@ export { trpcController } from '#decorators/trpc-controller.js'; export { TrpcRouteService } from '#services/route.service.js'; export { initTrpcModule, trpcRootModule, trpcModule } from '#decorators/trpc-init-hooks-and-metadata.js'; export { TRPC_ROOT, TRPC_OPTS } from '#types/constants.js'; -export { TrpcRequestDispatcher } from '#services/pre-router.js'; +export { TrpcRequestDispatcher } from '#services/request-dispatcher.js'; export { TrpcAppInitializer } from '#init/trpc-app-initializer.js'; export { TrpcApplication } from '#init/trpc-application.js'; export { TrpcService } from '#services/trpc.service.js'; diff --git a/packages/trpc/src/init/trpc-app-initializer.ts b/packages/trpc/src/init/trpc-app-initializer.ts index b18ef6925..50c789865 100644 --- a/packages/trpc/src/init/trpc-app-initializer.ts +++ b/packages/trpc/src/init/trpc-app-initializer.ts @@ -4,7 +4,7 @@ import { initTRPC } from '@trpc/server'; import type { RequestListener, TrpcRootModule } from '../types/types.js'; import { SERVER } from '../types/types.js'; -import { TrpcRequestDispatcher } from '#services/pre-router.js'; +import { TrpcRequestDispatcher } from '#services/request-dispatcher.js'; import type { HttpServer } from '#types/server-options.js'; import { TRPC_ROOT } from '#types/constants.js'; import { TrpcInternalService } from '#services/trpc-internal.service.js'; diff --git a/packages/trpc/src/services/pre-router.ts b/packages/trpc/src/services/request-dispatcher.ts similarity index 100% rename from packages/trpc/src/services/pre-router.ts rename to packages/trpc/src/services/request-dispatcher.ts diff --git a/packages/trpc/src/services/trpc-internal.service.ts b/packages/trpc/src/services/trpc-internal.service.ts index ab928adda..9fd3457ea 100644 --- a/packages/trpc/src/services/trpc-internal.service.ts +++ b/packages/trpc/src/services/trpc-internal.service.ts @@ -12,7 +12,7 @@ import { import { TRPC_ROOT } from '#types/constants.js'; import { TrpcRouterOpts, TrpcRootObject, ModuleWithTrpcRoutes, RouterOptions, TrpcRootModule } from '#types/types.js'; -import { TrpcRequestDispatcher } from './pre-router.js'; +import { TrpcRequestDispatcher } from './request-dispatcher.js'; import { isModuleWithTrpcRoutes } from '#utils/type.guards.js'; import { TrpcService } from '#services/trpc.service.js'; diff --git a/packages/trpc/src/trpc.module.ts b/packages/trpc/src/trpc.module.ts index a922af94e..cbdb830f9 100644 --- a/packages/trpc/src/trpc.module.ts +++ b/packages/trpc/src/trpc.module.ts @@ -1,7 +1,7 @@ import { ContextModule, featureModule } from '@ditsmod/core'; import { TrpcRouteExtension } from './extensions/trpc-route.extension.js'; -import { TrpcRequestDispatcherExtension } from './extensions/trpc-pre-router.extension.js'; +import { TrpcRequestDispatcherExtension } from './extensions/trpc-request-dispatcher.extension.js'; @featureModule({ imports: [ContextModule], diff --git a/website/docs/02-rest-application/00-rest-module.md b/website/docs/02-rest-application/00-rest-module.md index 976a98e83..171c05e68 100644 --- a/website/docs/02-rest-application/00-rest-module.md +++ b/website/docs/02-rest-application/00-rest-module.md @@ -75,7 +75,7 @@ export class MyCustomRouterModule {} З даного модуля експортується `RestRouteExtension`. Дане розширення повертає метадані з інтерфейсом [`Array`][2] - це масив динамічних метаданих, які призначені для створення обробників запитів. Кожен елемент цього масиву - це окремий роут. -## `DispatcherExtension` {#pre-router-extension} +## `DispatcherExtension` {#request-dispatcher-extension} З даного модуля також експортується `DispatcherExtension`. Дане розширення використовує метадані, які повертає `RestRouteExtension`, щоб створювати обробники HTTP-запитів. diff --git a/website/docs/02-rest-application/01-controllers-and-services.md b/website/docs/02-rest-application/01-controllers-and-services.md index 2d26e51e6..fc5ab0ee4 100644 --- a/website/docs/02-rest-application/01-controllers-and-services.md +++ b/website/docs/02-rest-application/01-controllers-and-services.md @@ -493,7 +493,7 @@ export class SomeModule {} [2]: /basic-components/modules/#DynamicModule [3]: /basic-components/dependency-injection/#injector-and-providers [5]: /rest-application/native-modules/body-parser/#retrieving-the-request-body -[6]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/services/pre-router.ts +[6]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.15/packages/rest/src/services/request-dispatcher.ts [7]: /basic-components/dependency-injection/ [9]: /basic-components/extensions/ [10]: #request-scoped-controller diff --git a/website/docs/02-rest-application/02-http-interceptors.md b/website/docs/02-rest-application/02-http-interceptors.md index d1ffe39d6..11dc97845 100644 --- a/website/docs/02-rest-application/02-http-interceptors.md +++ b/website/docs/02-rest-application/02-http-interceptors.md @@ -108,7 +108,7 @@ export class SomeModule {} [2]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/interceptors/default-http-frontend.ts [3]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/interceptors/default-http-backend.ts [5]: https://expressjs.com/en/guide/writing-middleware.html -[7]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/services/pre-router.ts +[7]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.15/packages/rest/src/services/request-dispatcher.ts [8]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/types/route-data.ts [9]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/body-parser/src/body-parser.extension.ts#L54 diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/00-rest-module.md b/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/00-rest-module.md index acd219223..8650516b9 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/00-rest-module.md +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/00-rest-module.md @@ -75,7 +75,7 @@ export class MyCustomRouterModule {} This module exports `RestRouteExtension`. This extension returns metadata with the [`Array`][2] interface — an array of dynamic metadata intended for creating request handlers. Each element of this array represents a separate route. -## `DispatcherExtension` {#pre-router-extension} +## `DispatcherExtension` {#request-dispatcher-extension} This module also exports `DispatcherExtension`. This extension uses the metadata returned by `RestRouteExtension` to create HTTP request handlers. diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/01-controllers-and-services.md b/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/01-controllers-and-services.md index 40609f21e..0e0b0bc47 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/01-controllers-and-services.md +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/01-controllers-and-services.md @@ -493,7 +493,7 @@ Also, if you import a provider from an external module and you have a provider w [2]: /basic-components/modules/#DynamicModule [3]: /basic-components/dependency-injection/#injector-and-providers [5]: /rest-application/native-modules/body-parser#retrieving-the-request-body -[6]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/services/pre-router.ts +[6]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.15/packages/rest/src/services/request-dispatcher.ts [7]: /basic-components/dependency-injection/ [9]: /basic-components/extensions/ [10]: #request-scoped-controller diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/02-http-interceptors.md b/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/02-http-interceptors.md index 3870325c5..416f5ed55 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/02-http-interceptors.md +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/02-http-interceptors.md @@ -108,7 +108,7 @@ In this case, the interceptors are passed in the module's metadata. They can als [2]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/interceptors/default-http-frontend.ts [3]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/interceptors/default-http-backend.ts [5]: https://expressjs.com/en/guide/writing-middleware.html -[7]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/services/pre-router.ts +[7]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.15/packages/rest/src/services/request-dispatcher.ts [8]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/rest/src/types/route-data.ts [9]: https://github.com/ditsmod/ditsmod/blob/3.0.0-next.8/packages/body-parser/src/body-parser.extension.ts#L54 From d0eb9db104f3f3cc20ac5ae29f451d744a8e53c0 Mon Sep 17 00:00:00 2001 From: KostyaTretyak Date: Wed, 15 Jul 2026 02:24:20 +0300 Subject: [PATCH 5/7] refactor(rest,sentry): make `requestListener()` as method --- .../rest/src/services/request-dispatcher.ts | 6 +- .../sentry/src/sentry-request-dispatcher.ts | 79 +++++++++---------- 2 files changed, 40 insertions(+), 45 deletions(-) diff --git a/packages/rest/src/services/request-dispatcher.ts b/packages/rest/src/services/request-dispatcher.ts index 775df21ab..4594285f3 100644 --- a/packages/rest/src/services/request-dispatcher.ts +++ b/packages/rest/src/services/request-dispatcher.ts @@ -2,7 +2,7 @@ import { HttpMethod, injectable, HttpStatus, SystemLogMediator } from '@ditsmod/ import { IncomingMessage, ServerResponse } from 'node:http'; import { Router } from './router.js'; -import { RawResponse, RequestListener } from './request.js'; +import { RawRequest, RawResponse } from './request.js'; @injectable() export class RequestDispatcher { @@ -11,7 +11,7 @@ export class RequestDispatcher { protected systemLogMediator: SystemLogMediator, ) {} - requestListener: RequestListener = async (rawReq, rawRes) => { + async requestListener(rawReq: RawRequest, rawRes: RawResponse) { const [pathname, search] = (rawReq.url || '').split('?'); let method = rawReq.method as HttpMethod; if (method == 'HEAD') { @@ -26,7 +26,7 @@ export class RequestDispatcher { await handle(rawReq, rawRes, params, search).catch((err) => { this.sendInternalServerError(rawRes, err); }); - }; + } /** * Logs an error and sends the user message about an internal server error (500). diff --git a/packages/sentry/src/sentry-request-dispatcher.ts b/packages/sentry/src/sentry-request-dispatcher.ts index 2c2cdfdc6..0b384d495 100644 --- a/packages/sentry/src/sentry-request-dispatcher.ts +++ b/packages/sentry/src/sentry-request-dispatcher.ts @@ -1,51 +1,46 @@ import * as Sentry from '@sentry/node'; -import { injectable, SystemLogMediator } from '@ditsmod/core'; -import { RequestDispatcher, Router } from '@ditsmod/rest'; -import type { RawResponse } from '@ditsmod/rest'; +import { injectable } from '@ditsmod/core'; +import { RequestDispatcher } from '@ditsmod/rest'; +import type { RawRequest, RawResponse } from '@ditsmod/rest'; @injectable() export class SentryRequestDispatcher extends RequestDispatcher { - constructor(router: Router, systemLogMediator: SystemLogMediator) { - super(router, systemLogMediator); - const originalRequestListener = this.requestListener; + override async requestListener(rawReq: RawRequest, rawRes: RawResponse) { + return Sentry.withIsolationScope(async () => { + const traceHeaders = rawReq.headers['sentry-trace']; + const baggage = rawReq.headers['baggage']; - this.requestListener = async (rawReq, rawRes) => { - return Sentry.withIsolationScope(async () => { - const traceHeaders = rawReq.headers['sentry-trace']; - const baggage = rawReq.headers['baggage']; - - return Sentry.continueTrace( - { - sentryTrace: traceHeaders as string, - baggage: baggage as string, - }, - () => { - const [pathname] = (rawReq.url || '').split('?'); - return Sentry.startSpan( - { - name: `${rawReq.method} ${pathname}`, - op: 'http.server', - }, - async (span) => { - try { - await originalRequestListener(rawReq, rawRes); - } catch (err) { - Sentry.captureException(err); - throw err; - } finally { - const statusCode = rawRes.statusCode; - if (statusCode >= 400) { - span?.setStatus({ code: 2, message: `HTTP ${statusCode}` }); - } else { - span?.setStatus({ code: 1 }); - } + return Sentry.continueTrace( + { + sentryTrace: traceHeaders as string, + baggage: baggage as string, + }, + () => { + const [pathname] = (rawReq.url || '').split('?'); + return Sentry.startSpan( + { + name: `${rawReq.method} ${pathname}`, + op: 'http.server', + }, + async (span) => { + try { + await super.requestListener(rawReq, rawRes); + } catch (err) { + Sentry.captureException(err); + throw err; + } finally { + const statusCode = rawRes.statusCode; + if (statusCode >= 400) { + span?.setStatus({ code: 2, message: `HTTP ${statusCode}` }); + } else { + span?.setStatus({ code: 1 }); } - }, - ); - }, - ); - }); - }; + } + }, + ); + }, + ); + }); } override sendInternalServerError(rawRes: RawResponse, err: Error) { From 15e9030fb33039bd964adcff5d9366bf341620fc Mon Sep 17 00:00:00 2001 From: KostyaTretyak Date: Wed, 15 Jul 2026 03:24:06 +0300 Subject: [PATCH 6/7] refactor(rest,trpc): rename `preRouter` to `requestDispatcher` --- .gitignore | 1 + packages/rest/src/init/rest-app-initializer.ts | 6 +++--- packages/trpc/src/init/trpc-app-initializer.ts | 6 +++--- packages/trpc/src/services/trpc-internal.service.ts | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index d7378457b..a52cac899 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules .agents/ +*.code-workspace dist* *.tgz *.log diff --git a/packages/rest/src/init/rest-app-initializer.ts b/packages/rest/src/init/rest-app-initializer.ts index 448f9258e..1944ed736 100644 --- a/packages/rest/src/init/rest-app-initializer.ts +++ b/packages/rest/src/init/rest-app-initializer.ts @@ -6,14 +6,14 @@ import type { HttpServer } from '#types/server-options.js'; import { SERVER } from '../top/constants.js'; export class RestAppInitializer extends BaseAppInitializer { - protected preRouter: RequestDispatcher; + protected requestDispatcher: RequestDispatcher; protected server: HttpServer; setServer(server: HttpServer) { this.server = server; } - requestListener: RequestListener = (rawReq, rawRes) => this.preRouter.requestListener(rawReq, rawRes); + requestListener: RequestListener = (rawReq, rawRes) => this.requestDispatcher.requestListener(rawReq, rawRes); protected override addDefaultProvidersPerApp() { this.normalizedModuleMeta.providersPerApp.unshift({ token: SERVER, useFactory: () => this.server }); @@ -22,7 +22,7 @@ export class RestAppInitializer extends BaseAppInitializer { override async bootstrapModulesAndExtensions() { const injectorPerApp = await super.bootstrapModulesAndExtensions(); - this.preRouter = injectorPerApp.get(RequestDispatcher) as RequestDispatcher; + this.requestDispatcher = injectorPerApp.get(RequestDispatcher) as RequestDispatcher; return injectorPerApp; } } diff --git a/packages/trpc/src/init/trpc-app-initializer.ts b/packages/trpc/src/init/trpc-app-initializer.ts index 50c789865..9946db9dc 100644 --- a/packages/trpc/src/init/trpc-app-initializer.ts +++ b/packages/trpc/src/init/trpc-app-initializer.ts @@ -11,7 +11,7 @@ import { TrpcInternalService } from '#services/trpc-internal.service.js'; import { TrpcService } from '#services/trpc.service.js'; export class TrpcAppInitializer extends BaseAppInitializer { - protected preRouter: TrpcRequestDispatcher; + protected requestDispatcher: TrpcRequestDispatcher; protected server: HttpServer; protected override addDefaultProvidersPerApp() { @@ -33,11 +33,11 @@ export class TrpcAppInitializer extends BaseAppInitializer { override async bootstrapModulesAndExtensions() { const injectorPerApp = await super.bootstrapModulesAndExtensions(); - this.preRouter = injectorPerApp.get(TrpcRequestDispatcher) as TrpcRequestDispatcher; + this.requestDispatcher = injectorPerApp.get(TrpcRequestDispatcher) as TrpcRequestDispatcher; return injectorPerApp; } - requestListener: RequestListener = (rawReq, rawRes) => this.preRouter.requestListener(rawReq, rawRes); + requestListener: RequestListener = (rawReq, rawRes) => this.requestDispatcher.requestListener(rawReq, rawRes); protected override overrideMetaAfterStage1(modRefId: ModRefId, normalizedModuleMeta: ProvidersByLevel): void { if (normalizedModuleMeta instanceof NormalizedModuleMeta) { diff --git a/packages/trpc/src/services/trpc-internal.service.ts b/packages/trpc/src/services/trpc-internal.service.ts index 9fd3457ea..51180a1ea 100644 --- a/packages/trpc/src/services/trpc-internal.service.ts +++ b/packages/trpc/src/services/trpc-internal.service.ts @@ -19,7 +19,7 @@ import { TrpcService } from '#services/trpc.service.js'; @injectable() export class TrpcInternalService { constructor( - protected preRouter: TrpcRequestDispatcher, + protected requestDispatcher: TrpcRequestDispatcher, protected trpcService: TrpcService, protected moduleManager: ModuleManager, @inject(TRPC_ROOT) protected t: TrpcRootObject, @@ -37,7 +37,7 @@ export class TrpcInternalService { const routerOpts = (mod.setAppRouterOptions?.() || {}) as unknown as TrpcRouterOpts; routerOpts.router = this.t.mergeRouters(...this.getRouters()); routerOpts.createContext = (opts) => opts; - this.preRouter.setTrpcRequestListener(routerOpts); + this.requestDispatcher.setTrpcRequestListener(routerOpts); } protected getRouters() { From 7fdcfa84ec24077f2c885b02659ba1e53eb74d2d Mon Sep 17 00:00:00 2001 From: KostyaTretyak Date: Wed, 15 Jul 2026 04:20:24 +0300 Subject: [PATCH 7/7] fix(rest): replace 501 by 404 --- examples/07-dynamically-composing-modules/e2e/main.spec.ts | 4 ++-- packages/rest/src/services/request-dispatcher.ts | 2 +- website/docs/02-rest-application/02-http-interceptors.md | 6 +++--- .../current/02-rest-application/02-http-interceptors.md | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/07-dynamically-composing-modules/e2e/main.spec.ts b/examples/07-dynamically-composing-modules/e2e/main.spec.ts index b0a38ee1e..dd18e67ac 100644 --- a/examples/07-dynamically-composing-modules/e2e/main.spec.ts +++ b/examples/07-dynamically-composing-modules/e2e/main.spec.ts @@ -25,7 +25,7 @@ describe('07-dynamically-composing-modules', () => { it('case 2', async () => { const { status } = await testAgent.get('/get-2'); - expect(status).toBe(501); + expect(status).toBe(404); }); xit('case 3', async () => { @@ -68,7 +68,7 @@ describe('07-dynamically-composing-modules', () => { it('case 9', async () => { const { status } = await testAgent.get('/get-2'); - expect(status).toBe(501); + expect(status).toBe(404); }); it('case 10', async () => { diff --git a/packages/rest/src/services/request-dispatcher.ts b/packages/rest/src/services/request-dispatcher.ts index 4594285f3..0f25da107 100644 --- a/packages/rest/src/services/request-dispatcher.ts +++ b/packages/rest/src/services/request-dispatcher.ts @@ -40,7 +40,7 @@ export class RequestDispatcher { } protected sendNotImplemented(rawRes: RawResponse) { - rawRes.statusCode = HttpStatus.NOT_IMPLEMENTED; + rawRes.statusCode = HttpStatus.NOT_FOUND; rawRes.end(); } diff --git a/website/docs/02-rest-application/02-http-interceptors.md b/website/docs/02-rest-application/02-http-interceptors.md index 11dc97845..23be08461 100644 --- a/website/docs/02-rest-application/02-http-interceptors.md +++ b/website/docs/02-rest-application/02-http-interceptors.md @@ -24,7 +24,7 @@ sidebar_position: 2 1. Ditsmod створює інстанс [RequestDispatcher][7] на рівні застосунку. 2. `RequestDispatcher` за допомогою роутера шукає обробника запиту відповідно до URI. -3. Якщо обробника запиту не знайдено, `RequestDispatcher` видає помилку зі статусом 501. +3. Якщо обробника запиту не знайдено, `RequestDispatcher` видає помилку зі статусом 404. 4. Якщо знайшовся обробник запиту, Ditsmod створює інстанс провайдера з токеном [HttpFrontend][2] на рівні запиту, ставить його першим у черзі інтерсепторів і автоматично викликає. By default, цей інтерсептор відповідає за встановлення значень для провайдерів з токенами `QUERY_PARAMS` та `PATH_PARAMS`. 5. Якщо в поточному маршруті є ґарди, то по-дефолту запускається `RequestScopedGuardedInterceptor` зразу після `HttpFrontend`. 6. Наступними можуть запуститись інші інтерсептори, це залежать від того, чи запустить їх попередній у черзі інтерсептор. @@ -40,7 +40,7 @@ sidebar_position: 2 Оскільки ланцюжок промісів починається від `RequestDispatcher`, і закінчується методом контролера, то резолвиться цей ланцюжок у зворотньому порядку - від методу контролера до `RequestDispatcher`. Це означає, що в інтерсепторі ви можете слухати результат резолву проміса, що повертає метод контролера. -Окрім цього, оскільки інстанси `RequestDispatcher`, `HttpFrontend`, `RequestScopedGuardedInterceptor` та `HttpBackend` створюються за допомогою DI, ви можете їх підміняти своєю версією відповідних класів. Наприклад, якщо ви хочете не просто відправити 501-ий статус у випадку відсутності потрібного роута, а хочете ще й додати певний текст чи змінити заголовки, ви можете підмінити [RequestDispatcher][7] своїм класом. +Окрім цього, оскільки інстанси `RequestDispatcher`, `HttpFrontend`, `RequestScopedGuardedInterceptor` та `HttpBackend` створюються за допомогою DI, ви можете їх підміняти своєю версією відповідних класів. Наприклад, якщо ви хочете не просто відправити 404-ий статус у випадку відсутності потрібного роута, а хочете ще й додати певний текст чи змінити заголовки, ви можете підмінити [RequestDispatcher][7] своїм класом. ### Робота в режимі route-scoped {#route-scoped-mode} @@ -48,7 +48,7 @@ sidebar_position: 2 1. Ditsmod створює інстанс [RequestDispatcher][7] на рівні застосунку. 2. `RequestDispatcher` за допомогою роутера шукає обробника запиту відповідно до URI. -3. Якщо обробника запиту не знайдено, `RequestDispatcher` видає помилку зі статусом 501. +3. Якщо обробника запиту не знайдено, `RequestDispatcher` видає помилку зі статусом 404. 4. Якщо знайшовся обробник запиту, Ditsmod використовує інстанс провайдера з токеном [HttpFrontend][2] на рівні роуту, ставить його першим у черзі інтерсепторів і автоматично викликає. By default, цей інтерсептор відповідає за встановлення значень `pathParams` та `queryParams` для `RequestContext`. 5. Якщо в поточному маршруті є ґарди, то по-дефолту запускається `RouteScopedGuardedInterceptor` зразу після `HttpFrontend`. 6. Наступними можуть запуститись інші інтерсептори, це залежать від того, чи запустить їх попередній у черзі інтерсептор. diff --git a/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/02-http-interceptors.md b/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/02-http-interceptors.md index 416f5ed55..d1eaf6468 100644 --- a/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/02-http-interceptors.md +++ b/website/i18n/en/docusaurus-plugin-content-docs/current/02-rest-application/02-http-interceptors.md @@ -24,7 +24,7 @@ HTTP request processing has the following workflow: 1. Ditsmod creates an instance of [RequestDispatcher][7] at the application level. 2. `RequestDispatcher` uses the router to search for the request handler according to the URI. -3. If the request handler is not found, `RequestDispatcher` issues a 501 error. +3. If the request handler is not found, `RequestDispatcher` issues a 404 error. 4. If a request handler is found, Ditsmod creates a provider instance with the [HttpFrontend][2] token at the request level, places it first in the queue of interceptors, and automatically calls it. By default, this interceptor is responsible for setting values for providers with `QUERY_PARAMS` and `PATH_PARAMS` tokens. 5. If there are guards in the current route, then by default `RequestScopedGuardedInterceptor` is run immediately after `HttpFrontend`. 6. Other interceptors may be launched next, depending on whether the previous interceptor in the queue will launch them. @@ -40,7 +40,7 @@ So, the approximate order of processing the request is as follows: Since the promise chain starts with `RequestDispatcher` and ends with the controller method, this chain will be resolved in reverse order - from the controller method to `RequestDispatcher`. This means that in the interceptor you can listen for the result of promise resolve, which returns the method of the controller. -In addition, because `RequestDispatcher`, `HttpFrontend`, `RequestScopedGuardedInterceptor`, and `HttpBackend` instances are created using DI, you can replace them with your own version of the respective classes. For example, if you don't just want to send a 501 status when the required route is missing, but also want to add some text or change headers, you can substitute [RequestDispatcher][7] with your own class. +In addition, because `RequestDispatcher`, `HttpFrontend`, `RequestScopedGuardedInterceptor`, and `HttpBackend` instances are created using DI, you can replace them with your own version of the respective classes. For example, if you don't just want to send a 404 status when the required route is missing, but also want to add some text or change headers, you can substitute [RequestDispatcher][7] with your own class. ### Route-scoped mode {#route-scoped-mode} @@ -48,7 +48,7 @@ A route-scoped interceptor operates very similarly to an request-scoped intercep 1. Ditsmod creates an instance of [RequestDispatcher][7] at the application level. 2. `RequestDispatcher` uses the router to search for the request handler according to the URI. -3. If the request handler is not found, `RequestDispatcher` issues a 501 error. +3. If the request handler is not found, `RequestDispatcher` issues a 404 error. 4. If a request handler is found, Ditsmod uses a provider instance with the [HttpFrontend][2] token at the route level, places it first in the interceptor queue, and automatically invokes it. By default, this interceptor is responsible for setting `pathParams` and `queryParams` values for `RequestContext`. 5. If there are guards in the current route, then by default `RouteScopedGuardedInterceptor` is run immediately after `HttpFrontend`. 6. Other interceptors may be launched next, depending on whether the previous interceptor in the queue will launch them.