From a573acedd0317f3472cb0f8b95f6aa15315312e5 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:13:25 +0100 Subject: [PATCH 01/63] fix: local storage, and package overrides --- apps/client/package.json | 2 +- apps/server/package.json | 24 +- .../core/attachment/attachment.controller.ts | 5 + .../src/core/user/dto/update-user.dto.ts | 4 - apps/server/src/core/user/user.service.ts | 4 - .../workspace/dto/update-workspace.dto.ts | 5 - .../src/integrations/export/export.service.ts | 99 +++- .../storage/drivers/local.driver.spec.ts | 67 +++ .../storage/drivers/local.driver.ts | 9 +- package.json | 10 +- pnpm-lock.yaml | 486 +++++++++--------- 11 files changed, 409 insertions(+), 306 deletions(-) create mode 100644 apps/server/src/integrations/storage/drivers/local.driver.spec.ts diff --git a/apps/client/package.json b/apps/client/package.json index 6b8a8b60d..bdf222097 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -42,7 +42,7 @@ "mantine-form-zod-resolver": "^1.3.0", "mermaid": "^11.13.0", "mitt": "^3.0.1", - "posthog-js": "1.363.1", + "posthog-js": "1.370.0", "react": "^18.3.1", "react-arborist": "3.4.0", "react-clear-modal": "^2.0.18", diff --git a/apps/server/package.json b/apps/server/package.json index 4aca4acd0..97af8db7d 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -38,8 +38,8 @@ "@aws-sdk/s3-request-presigner": "3.1014.0", "@clickhouse/client": "^1.18.2", "@fastify/cookie": "^11.0.2", - "@fastify/multipart": "^9.4.0", - "@fastify/static": "^9.0.0", + "@fastify/multipart": "^10.0.0", + "@fastify/static": "^9.1.3", "@keyv/redis": "^5.1.6", "@langchain/core": "1.1.39", "@langchain/textsplitters": "1.0.1", @@ -48,19 +48,19 @@ "@nestjs-labs/nestjs-ioredis": "^11.0.4", "@nestjs/bullmq": "^11.0.4", "@nestjs/cache-manager": "^3.1.0", - "@nestjs/common": "^11.1.18", - "@nestjs/config": "^4.0.3", - "@nestjs/core": "^11.1.18", + "@nestjs/common": "^11.1.19", + "@nestjs/config": "^4.0.4", + "@nestjs/core": "^11.1.19", "@nestjs/event-emitter": "^3.0.1", "@nestjs/jwt": "11.0.2", "@nestjs/mapped-types": "^2.1.1", "@nestjs/passport": "^11.0.5", - "@nestjs/platform-fastify": "^11.1.18", - "@nestjs/platform-socket.io": "^11.1.18", - "@nestjs/schedule": "^6.1.1", + "@nestjs/platform-fastify": "^11.1.19", + "@nestjs/platform-socket.io": "^11.1.19", + "@nestjs/schedule": "^6.1.3", "@nestjs/terminus": "^11.1.1", "@nestjs/throttler": "^6.5.0", - "@nestjs/websockets": "^11.1.18", + "@nestjs/websockets": "^11.1.19", "@node-saml/passport-saml": "^5.1.0", "@react-email/components": "1.0.10", "@react-email/render": "2.0.4", @@ -69,7 +69,7 @@ "ai-sdk-ollama": "^3.8.1", "bcrypt": "^6.0.0", "bowser": "^2.14.1", - "bullmq": "^5.71.0", + "bullmq": "^5.76.0", "cache-manager": "^7.2.8", "cheerio": "^1.2.0", "class-transformer": "^0.5.1", @@ -123,9 +123,9 @@ }, "devDependencies": { "@eslint/js": "^9.28.0", - "@nestjs/cli": "^11.0.18", + "@nestjs/cli": "^11.0.21", "@nestjs/schematics": "^11.0.10", - "@nestjs/testing": "^11.1.18", + "@nestjs/testing": "^11.1.19", "@types/bcrypt": "^6.0.0", "@types/debounce": "^1.2.4", "@types/fs-extra": "^11.0.4", diff --git a/apps/server/src/core/attachment/attachment.controller.ts b/apps/server/src/core/attachment/attachment.controller.ts index 7b24cc356..784e527e6 100644 --- a/apps/server/src/core/attachment/attachment.controller.ts +++ b/apps/server/src/core/attachment/attachment.controller.ts @@ -53,6 +53,7 @@ import { EnvironmentService } from '../../integrations/environment/environment.s import { TokenService } from '../auth/services/token.service'; import { JwtAttachmentPayload, JwtType } from '../auth/dto/jwt-payload'; import * as path from 'path'; +import { sanitize } from 'sanitize-filename-ts'; import { AttachmentInfoDto, RemoveIconDto } from './dto/attachment.dto'; import { PageAccessService } from '../page/page-access/page-access.service'; import { AuditEvent, AuditResource } from '../../common/events/audit-events'; @@ -356,6 +357,10 @@ export class AttachmentController { throw new BadRequestException('Invalid image attachment type'); } + if (!fileName || sanitize(fileName) !== fileName) { + throw new BadRequestException('Invalid file name'); + } + const filenameWithoutExt = path.basename(fileName, path.extname(fileName)); if (!isValidUUID(filenameWithoutExt)) { throw new BadRequestException('Invalid file id'); diff --git a/apps/server/src/core/user/dto/update-user.dto.ts b/apps/server/src/core/user/dto/update-user.dto.ts index f1c02c516..9d8ef8ef8 100644 --- a/apps/server/src/core/user/dto/update-user.dto.ts +++ b/apps/server/src/core/user/dto/update-user.dto.ts @@ -13,10 +13,6 @@ import { CreateUserDto } from '../../auth/dto/create-user.dto'; export class UpdateUserDto extends PartialType( OmitType(CreateUserDto, ['password'] as const), ) { - @IsOptional() - @IsString() - avatarUrl: string; - @IsOptional() @IsBoolean() fullPageWidth: boolean; diff --git a/apps/server/src/core/user/user.service.ts b/apps/server/src/core/user/user.service.ts index fa2298274..7a1439767 100644 --- a/apps/server/src/core/user/user.service.ts +++ b/apps/server/src/core/user/user.service.ts @@ -110,10 +110,6 @@ export class UserService { user.email = updateUserDto.email; } - if (updateUserDto.avatarUrl) { - user.avatarUrl = updateUserDto.avatarUrl; - } - if (updateUserDto.locale) { user.locale = updateUserDto.locale; } diff --git a/apps/server/src/core/workspace/dto/update-workspace.dto.ts b/apps/server/src/core/workspace/dto/update-workspace.dto.ts index 4b1482084..a08b1e524 100644 --- a/apps/server/src/core/workspace/dto/update-workspace.dto.ts +++ b/apps/server/src/core/workspace/dto/update-workspace.dto.ts @@ -5,15 +5,10 @@ import { IsBoolean, IsInt, IsOptional, - IsString, Min, } from 'class-validator'; export class UpdateWorkspaceDto extends PartialType(CreateWorkspaceDto) { - @IsOptional() - @IsString() - logo: string; - @IsOptional() @IsArray() emailDomains: string[]; diff --git a/apps/server/src/integrations/export/export.service.ts b/apps/server/src/integrations/export/export.service.ts index 3f8da1bf9..b4bc73fac 100644 --- a/apps/server/src/integrations/export/export.service.ts +++ b/apps/server/src/integrations/export/export.service.ts @@ -39,6 +39,8 @@ import { } from '../../common/helpers/prosemirror/utils'; import { htmlToMarkdown } from '@docmost/editor-ext'; +type AllowedAttachment = { id: string; fileName: string; filePath: string }; + @Injectable() export class ExportService { private readonly logger = new Logger(ExportService.name); @@ -272,6 +274,12 @@ export class ExportService { computeLocalPath(tree, format, null, '', slugIdToPath); + // Batch resolve attachments once for the whole export so we only run the + // owning-page view check a single time, regardless of page count. + const allowedAttachments = includeAttachments + ? await this.resolveAccessibleAttachments(tree, userId, ignorePermissions) + : new Map(); + const stack: { folder: JSZip; parentPageId: string | null }[] = [ { folder: zip, parentPageId: null }, ]; @@ -301,7 +309,7 @@ export class ExportService { ); if (includeAttachments) { - await this.zipAttachments(updatedJsonContent, page.spaceId, folder); + await this.zipAttachments(updatedJsonContent, folder, allowedAttachments); updatedJsonContent = updateAttachmentUrlsToLocalPaths(updatedJsonContent); } @@ -347,31 +355,80 @@ export class ExportService { zip.file('docmost-metadata.json', JSON.stringify(metadata, null, 2)); } - async zipAttachments(prosemirrorJson: any, spaceId: string, zip: JSZip) { + async zipAttachments( + prosemirrorJson: any, + zip: JSZip, + allowed: Map, + ) { const attachmentIds = getAttachmentIds(prosemirrorJson); - if (attachmentIds.length > 0) { - const attachments = await this.db - .selectFrom('attachments') - .select(['id', 'fileName', 'filePath']) - .where('id', 'in', attachmentIds) - .where('spaceId', '=', spaceId) - .execute(); + await Promise.all( + attachmentIds.map(async (id) => { + const attachment = allowed.get(id); + if (!attachment) return; + try { + const fileBuffer = await this.storageService.read( + attachment.filePath, + ); + const filePath = `/files/${attachment.id}/${attachment.fileName}`; + zip.file(filePath, fileBuffer); + } catch (err) { + this.logger.debug(`Attachment export error ${attachment.id}`, err); + } + }), + ); + } - await Promise.all( - attachments.map(async (attachment) => { - try { - const fileBuffer = await this.storageService.read( - attachment.filePath, - ); - const filePath = `/files/${attachment.id}/${attachment.fileName}`; - zip.file(filePath, fileBuffer); - } catch (err) { - this.logger.debug(`Attachment export error ${attachment.id}`, err); - } - }), + private async resolveAccessibleAttachments( + tree: PageExportTree, + userId: string | undefined, + ignorePermissions: boolean, + ): Promise> { + const allAttachmentIds = new Set(); + let spaceId: string | undefined; + for (const siblings of Object.values(tree)) { + for (const page of siblings) { + if (!spaceId) spaceId = page.spaceId; + for (const id of getAttachmentIds(getProsemirrorContent(page.content))) { + allAttachmentIds.add(id); + } + } + } + + if (allAttachmentIds.size === 0 || !spaceId) { + return new Map(); + } + + const attachments = await this.db + .selectFrom('attachments') + .select(['id', 'fileName', 'filePath', 'pageId']) + .where('id', 'in', [...allAttachmentIds]) + .where('spaceId', '=', spaceId) + .execute(); + + let visible = attachments; + if (!ignorePermissions && userId) { + const ownerPageIds = [ + ...new Set( + attachments + .map((a) => a.pageId) + .filter((id): id is string => !!id), + ), + ]; + const accessible = ownerPageIds.length + ? await this.pagePermissionRepo.filterAccessiblePageIds({ + pageIds: ownerPageIds, + userId, + spaceId, + }) + : []; + const accessibleSet = new Set(accessible); + visible = attachments.filter( + (a) => a.pageId && accessibleSet.has(a.pageId), ); } + + return new Map(visible.map((a) => [a.id, a])); } async turnPageMentionsToLinks( diff --git a/apps/server/src/integrations/storage/drivers/local.driver.spec.ts b/apps/server/src/integrations/storage/drivers/local.driver.spec.ts new file mode 100644 index 000000000..ccdddcc5d --- /dev/null +++ b/apps/server/src/integrations/storage/drivers/local.driver.spec.ts @@ -0,0 +1,67 @@ +import { resolve, sep } from 'path'; +import { LocalDriver } from './local.driver'; + +type FullPath = (filePath: string) => string; + +describe('LocalDriver._fullPath', () => { + const ROOT = resolve('/data/storage'); + const driver = new LocalDriver({ storagePath: ROOT }); + const fullPath = ((driver as any)._fullPath as FullPath).bind(driver); + + describe('legitimate inputs (behavior preserved)', () => { + it.each([ + ['workspace-id/avatars/uuid.png', `${ROOT}${sep}workspace-id${sep}avatars${sep}uuid.png`], + ['workspace-id/files/uuid/file.pdf', `${ROOT}${sep}workspace-id${sep}files${sep}uuid${sep}file.pdf`], + ['a/b/c/d/e.bin', `${ROOT}${sep}a${sep}b${sep}c${sep}d${sep}e.bin`], + ['', ROOT], + ['.', ROOT], + ['./x/y.png', `${ROOT}${sep}x${sep}y.png`], + ['a//b', `${ROOT}${sep}a${sep}b`], + ['a/b/../c', `${ROOT}${sep}a${sep}c`], + ])('resolves %j to %j', (input, expected) => { + expect(fullPath(input)).toBe(expected); + }); + }); + + describe('traversal rejected', () => { + it.each([ + '../etc/passwd', + '../../../etc/passwd', + 'workspace/../../../etc/passwd', + '..', + '../..', + 'a/../../..', + ])('throws for %j', (input) => { + expect(() => fullPath(input)).toThrow('Invalid file path'); + }); + }); + + describe('absolute path rejected', () => { + it.each([ + '/etc/passwd', + '/root/.ssh/id_rsa', + sep + 'absolute', + ])('throws for %j', (input) => { + expect(() => fullPath(input)).toThrow('Invalid file path'); + }); + }); + + describe('prefix-confusion rejected', () => { + it('rejects a sibling directory whose name starts with the storage root', () => { + const siblingDriver = new LocalDriver({ storagePath: '/data/storage' }); + const siblingFullPath = ((siblingDriver as any)._fullPath as FullPath).bind(siblingDriver); + // Attempt to reach /data/storage-evil/secret by traversal: + // resolve('/data/storage', '../storage-evil/secret') === '/data/storage-evil/secret' + // Without the `+ sep` guard, a startsWith check would match. + expect(() => siblingFullPath('../storage-evil/secret')).toThrow('Invalid file path'); + }); + }); + + describe('storage root itself', () => { + it('accepts the root when input resolves to it', () => { + expect(fullPath('')).toBe(ROOT); + expect(fullPath('.')).toBe(ROOT); + expect(fullPath('a/..')).toBe(ROOT); + }); + }); +}); diff --git a/apps/server/src/integrations/storage/drivers/local.driver.ts b/apps/server/src/integrations/storage/drivers/local.driver.ts index 39342c619..60be7c5df 100644 --- a/apps/server/src/integrations/storage/drivers/local.driver.ts +++ b/apps/server/src/integrations/storage/drivers/local.driver.ts @@ -3,7 +3,7 @@ import { LocalStorageConfig, StorageOption, } from '../interfaces'; -import { join, dirname } from 'path'; +import { dirname, resolve, sep } from 'path'; import * as fs from 'fs-extra'; import { Readable } from 'stream'; import { createReadStream, createWriteStream } from 'node:fs'; @@ -17,7 +17,12 @@ export class LocalDriver implements StorageDriver { } private _fullPath(filePath: string): string { - return join(this.config.storagePath, filePath); + const storageRoot = resolve(this.config.storagePath); + const fullPath = resolve(storageRoot, filePath); + if (fullPath !== storageRoot && !fullPath.startsWith(storageRoot + sep)) { + throw new Error('Invalid file path'); + } + return fullPath; } async upload(filePath: string, file: Buffer | Readable): Promise { diff --git a/package.json b/package.json index bf7b27618..6d3d97c2d 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "cross-env": "^10.1.0", "date-fns": "^4.1.0", "diff": "8.0.3", - "dompurify": "^3.3.3", + "dompurify": "3.4.1", "fractional-indexing-jittered": "^1.0.0", "highlight.js": "^11.11.1", "image-dimensions": "^2.5.0", @@ -102,9 +102,9 @@ "y-prosemirror": "1.3.7", "glob": "13.0.6", "ws": "8.20.0", - "dompurify": "3.3.3", + "dompurify": "3.4.1", "tmp": "0.2.5", - "hono": "4.12.12", + "hono": "4.12.14", "mermaid": "11.13.0", "nanoid@^3": "3.3.8", "socket.io-parser": "4.2.6", @@ -123,7 +123,7 @@ "flatted": "3.4.2", "picomatch@<2.3.2": "2.3.2", "picomatch@>=4.0.0 <4.0.4": "4.0.4", - "fastify": "5.8.3", + "fastify": "5.8.5", "yaml@>=1.0.0 <1.10.3": "1.10.3", "yaml@>=2.0.0 <2.8.3": "2.8.3", "path-to-regexp@^8": "8.4.0", @@ -131,7 +131,7 @@ "@xmldom/xmldom": "0.8.12", "handlebars": "4.7.9", "axios": "1.15.0", - "langsmith": "0.5.18", + "langsmith": "0.5.19", "follow-redirects": "1.16.0" }, "neverBuiltDependencies": [] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d30859b71..56dd6d794 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,9 +9,9 @@ overrides: y-prosemirror: 1.3.7 glob: 13.0.6 ws: 8.20.0 - dompurify: 3.3.3 + dompurify: 3.4.1 tmp: 0.2.5 - hono: 4.12.12 + hono: 4.12.14 mermaid: 11.13.0 nanoid@^3: 3.3.8 socket.io-parser: 4.2.6 @@ -30,7 +30,7 @@ overrides: flatted: 3.4.2 picomatch@<2.3.2: 2.3.2 picomatch@>=4.0.0 <4.0.4: 4.0.4 - fastify: 5.8.3 + fastify: 5.8.5 yaml@>=1.0.0 <1.10.3: 1.10.3 yaml@>=2.0.0 <2.8.3: 2.8.3 path-to-regexp@^8: 8.4.0 @@ -38,7 +38,7 @@ overrides: '@xmldom/xmldom': 0.8.12 handlebars: 4.7.9 axios: 1.15.0 - langsmith: 0.5.18 + langsmith: 0.5.19 follow-redirects: 1.16.0 patchedDependencies: @@ -180,8 +180,8 @@ importers: specifier: 8.0.3 version: 8.0.3 dompurify: - specifier: 3.3.3 - version: 3.3.3 + specifier: 3.4.1 + version: 3.4.1 fractional-indexing-jittered: specifier: ^1.0.0 version: 1.0.0 @@ -343,8 +343,8 @@ importers: specifier: ^3.0.1 version: 3.0.1 posthog-js: - specifier: 1.363.1 - version: 1.363.1 + specifier: 1.370.0 + version: 1.370.0 react: specifier: ^18.3.1 version: 18.3.1 @@ -482,11 +482,11 @@ importers: specifier: ^11.0.2 version: 11.0.2 '@fastify/multipart': - specifier: ^9.4.0 - version: 9.4.0 + specifier: ^10.0.0 + version: 10.0.0 '@fastify/static': - specifier: ^9.0.0 - version: 9.0.0 + specifier: ^9.1.3 + version: 9.1.3 '@keyv/redis': specifier: ^5.1.6 version: 5.1.6(keyv@5.6.0) @@ -501,55 +501,55 @@ importers: version: 1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6) '@nest-lab/throttler-storage-redis': specifier: ^1.2.0 - version: 1.2.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(@nestjs/throttler@6.5.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2))(ioredis@5.10.1)(reflect-metadata@0.2.2) + version: 1.2.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(@nestjs/throttler@6.5.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2))(ioredis@5.10.1)(reflect-metadata@0.2.2) '@nestjs-labs/nestjs-ioredis': specifier: ^11.0.4 - version: 11.0.4(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(ioredis@5.10.1) + version: 11.0.4(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(ioredis@5.10.1) '@nestjs/bullmq': specifier: ^11.0.4 - version: 11.0.4(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(bullmq@5.71.0) + version: 11.0.4(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(bullmq@5.76.0) '@nestjs/cache-manager': specifier: ^3.1.0 - version: 3.1.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(cache-manager@7.2.8)(keyv@5.6.0)(rxjs@7.8.2) + version: 3.1.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(cache-manager@7.2.8)(keyv@5.6.0)(rxjs@7.8.2) '@nestjs/common': - specifier: ^11.1.18 - version: 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + specifier: ^11.1.19 + version: 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/config': - specifier: ^4.0.3 - version: 4.0.3(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2) + specifier: ^4.0.4 + version: 4.0.4(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2) '@nestjs/core': - specifier: ^11.1.18 - version: 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + specifier: ^11.1.19 + version: 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/event-emitter': specifier: ^3.0.1 - version: 3.0.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18) + version: 3.0.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19) '@nestjs/jwt': specifier: 11.0.2 - version: 11.0.2(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)) + version: 11.0.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)) '@nestjs/mapped-types': specifier: ^2.1.1 - version: 2.1.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2) + version: 2.1.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2) '@nestjs/passport': specifier: ^11.0.5 - version: 11.0.5(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0) + version: 11.0.5(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0) '@nestjs/platform-fastify': - specifier: ^11.1.18 - version: 11.1.18(@fastify/static@9.0.0)(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18) + specifier: ^11.1.19 + version: 11.1.19(@fastify/static@9.1.3)(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19) '@nestjs/platform-socket.io': - specifier: ^11.1.18 - version: 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(rxjs@7.8.2) + specifier: ^11.1.19 + version: 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(rxjs@7.8.2) '@nestjs/schedule': - specifier: ^6.1.1 - version: 6.1.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18) + specifier: ^6.1.3 + version: 6.1.3(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19) '@nestjs/terminus': specifier: ^11.1.1 - version: 11.1.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + version: 11.1.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/throttler': specifier: ^6.5.0 - version: 6.5.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2) + version: 6.5.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2) '@nestjs/websockets': - specifier: ^11.1.18 - version: 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(@nestjs/platform-socket.io@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + specifier: ^11.1.19 + version: 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(@nestjs/platform-socket.io@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@node-saml/passport-saml': specifier: ^5.1.0 version: 5.1.0 @@ -575,8 +575,8 @@ importers: specifier: ^2.14.1 version: 2.14.1 bullmq: - specifier: ^5.71.0 - version: 5.71.0 + specifier: ^5.76.0 + version: 5.76.0 cache-manager: specifier: ^7.2.8 version: 7.2.8 @@ -642,13 +642,13 @@ importers: version: 5.1.7 nestjs-cls: specifier: ^6.2.0 - version: 6.2.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + version: 6.2.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) nestjs-kysely: specifier: ^3.1.2 - version: 3.1.2(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(kysely@0.28.14)(reflect-metadata@0.2.2) + version: 3.1.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(kysely@0.28.14)(reflect-metadata@0.2.2) nestjs-pino: specifier: ^4.6.1 - version: 4.6.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2) + version: 4.6.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2) nodemailer: specifier: ^8.0.5 version: 8.0.5 @@ -732,14 +732,14 @@ importers: specifier: ^9.28.0 version: 9.39.4 '@nestjs/cli': - specifier: ^11.0.18 - version: 11.0.18(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@25.5.0) + specifier: ^11.0.21 + version: 11.0.21(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@25.5.0) '@nestjs/schematics': specifier: ^11.0.10 version: 11.0.10(chokidar@4.0.3)(typescript@5.9.3) '@nestjs/testing': - specifier: ^11.1.18 - version: 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18) + specifier: ^11.1.19 + version: 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19) '@types/bcrypt': specifier: ^6.0.0 version: 6.0.0 @@ -808,7 +808,7 @@ importers: version: 29.4.6(@babel/core@7.28.5)(@jest/transform@30.3.0)(@jest/types@30.3.0)(babel-jest@30.3.0(@babel/core@7.28.5))(jest-util@30.3.0)(jest@30.3.0(@types/node@25.5.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@25.5.0)(typescript@5.9.3)))(typescript@5.9.3) ts-loader: specifier: ^9.5.7 - version: 9.5.7(typescript@5.9.3)(webpack@5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5))) + version: 9.5.7(typescript@5.9.3)(webpack@5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5))) ts-node: specifier: ^10.9.2 version: 10.9.2(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@25.5.0)(typescript@5.9.3) @@ -880,8 +880,17 @@ packages: chokidar: optional: true - '@angular-devkit/schematics-cli@19.2.23': - resolution: {integrity: sha512-M8g7Gu3Lc5bbzijd2QLcQhfdpfMVE32YXQ6FIkA8x91Kmd2gb8aVvGYPLYUN5619P+ABWhN5Dn2PKuk01zz3vg==} + '@angular-devkit/core@19.2.24': + resolution: {integrity: sha512-Kd49warf6U/EyWe5BszF/eebN3zQ3bk7tgfEljAw8q/rX95UUtriJubWvp6pgzHfzBA4jwq8f+QiNZB8eBEXPA==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + peerDependencies: + chokidar: ^4.0.0 + peerDependenciesMeta: + chokidar: + optional: true + + '@angular-devkit/schematics-cli@19.2.24': + resolution: {integrity: sha512-bsStZQG67J1HBqTmWxtIcobvgrn32L4UOdL7hGyOru5VxDWPNA8pRnDYavT3hnJeBkJYPoQIw8u7Dm0ecoQprw==} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true @@ -889,6 +898,10 @@ packages: resolution: {integrity: sha512-Jzs7YM4X6azmHU7Mw5tQSPMuvaqYS8SLnZOJbtiXCy1JyuW9bm/WBBecNHMiuZ8LHXKhvQ6AVX1tKrzF6uiDmw==} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@angular-devkit/schematics@19.2.24': + resolution: {integrity: sha512-lnw+ZM1Io+cJAkReC0NPDjqObL8NtKzKIkdgEEKC8CUmkhurYhedbicN8Y8NYHgG1uLd2GozW3+/QqPRZaN+Lw==} + engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + '@antfu/install-pkg@1.1.0': resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} @@ -2238,8 +2251,8 @@ packages: '@fastify/merge-json-schemas@0.2.1': resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==} - '@fastify/multipart@9.4.0': - resolution: {integrity: sha512-Z404bzZeLSXTBmp/trCBuoVFX28pM7rhv849Q5TsbTFZHuk1lc4QjQITTPK92DKVpXmNtJXeHSSc7GYvqFpxAQ==} + '@fastify/multipart@10.0.0': + resolution: {integrity: sha512-pUx3Z1QStY7E7kwvDTIvB6P+rF5lzP+iqPgZyJyG3yBJVPvQaZxzDHYbQD89rbY0ciXrMOyGi8ezHDVexLvJDA==} '@fastify/proxy-addr@5.0.0': resolution: {integrity: sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==} @@ -2247,8 +2260,8 @@ packages: '@fastify/send@4.1.0': resolution: {integrity: sha512-TMYeQLCBSy2TOFmV95hQWkiTYgC/SEx7vMdV+wnZVX4tt8VBLKzmH8vV9OzJehV0+XBfg+WxPMt5wp+JBUKsVw==} - '@fastify/static@9.0.0': - resolution: {integrity: sha512-r64H8Woe/vfilg5RTy7lwWlE8ZZcTrc3kebYFMEUBrMqlydhQyoiExQXdYAy2REVpST/G35+stAM8WYp1WGmMA==} + '@fastify/static@9.1.3': + resolution: {integrity: sha512-aXrYtsiryLhRxRNaxNqsn7FUISeb7rB9q4eHUPIot5aeQBLNahnz1m6thzm7JWC1poSGXS9XrX8DvuMivp2hkQ==} '@floating-ui/core@1.7.3': resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} @@ -2301,7 +2314,7 @@ packages: resolution: {integrity: sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ==} engines: {node: '>=18.14.1'} peerDependencies: - hono: 4.12.12 + hono: 4.12.14 '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} @@ -2472,9 +2485,6 @@ packages: '@types/node': optional: true - '@ioredis/commands@1.5.0': - resolution: {integrity: sha512-eUgLqrMf8nJkZxT24JvVRrQya1vZkQh8BBeYNwGDqa5I0VUi8ACx7uFvAaLxintokpTenkK6DASvo/bvNbBGow==} - '@ioredis/commands@1.5.1': resolution: {integrity: sha512-JH8ZL/ywcJyR9MmJ5BNqZllXNZQqQbnVZOqpPQqE1vHiFgAw4NHbvE0FOduNU8IX9babitBT46571OnPTT0Zcw==} @@ -2860,8 +2870,8 @@ packages: keyv: '>=5' rxjs: ^7.8.1 - '@nestjs/cli@11.0.18': - resolution: {integrity: sha512-z72OS+sFrDgIkNu/e/vUhbnjHZwAYQS8fBJKXLiFyz8059IVuY2FKebV2YMxyhY+920d4LX1hBIAGL5qQNdR7g==} + '@nestjs/cli@11.0.21': + resolution: {integrity: sha512-F8mV0Sj/zVEouzR3NxBuJy08YHTUOmC5Xdcx3qIIaJWzrm8Vw86CHkhkaPBJ5ewRMHPDCShPmhsfwhpCcjts3A==} engines: {node: '>= 20.11'} hasBin: true peerDependencies: @@ -2873,8 +2883,8 @@ packages: '@swc/core': optional: true - '@nestjs/common@11.1.18': - resolution: {integrity: sha512-0sLq8Z+TIjLnz1Tqp0C/x9BpLbqpt1qEu0VcH4/fkE0y3F5JxhfK1AdKQ/SPbKhKgwqVDoY4gS8GQr2G6ujaWg==} + '@nestjs/common@11.1.19': + resolution: {integrity: sha512-qeiTt2tv+e5QyDKqG8HlVZb2wx64FEaSGFJouqTSRs+kG44iTfl3xlz1XqVped+rihx4hmjWgL5gkhtdK3E6+Q==} peerDependencies: class-transformer: '>=0.4.1' class-validator: '>=0.13.2' @@ -2886,14 +2896,14 @@ packages: class-validator: optional: true - '@nestjs/config@4.0.3': - resolution: {integrity: sha512-FQ3M3Ohqfl+nHAn5tp7++wUQw0f2nAk+SFKe8EpNRnIifPqvfJP6JQxPKtFLMOHbyer4X646prFG4zSRYEssQQ==} + '@nestjs/config@4.0.4': + resolution: {integrity: sha512-CJPjNitr0bAufSEnRe2N+JbnVmMmDoo6hvKCPzXgZoGwJSmp/dZPk9f/RMbuD/+Q1ZJPjwsRpq0vxna++Knwow==} peerDependencies: '@nestjs/common': ^10.0.0 || ^11.0.0 rxjs: ^7.1.0 - '@nestjs/core@11.1.18': - resolution: {integrity: sha512-wR3DtGyk/LUAiPtbXDuWJJwVkWElKBY0sqnTzf9d4uM3+X18FRZhK7WFc47czsIGOdWuRsMeLYV+1Z9dO4zDEQ==} + '@nestjs/core@11.1.19': + resolution: {integrity: sha512-6nJkWa2efrYi+XlU686J9y5L7OvxpLVjT0T/sxRKE7Jvpffiihelup4WSvLvRhdHDjj/5SuoWEwqReXAaaeHmw==} engines: {node: '>= 20'} peerDependencies: '@nestjs/common': ^11.0.0 @@ -2940,8 +2950,8 @@ packages: '@nestjs/common': ^10.0.0 || ^11.0.0 passport: ^0.5.0 || ^0.6.0 || ^0.7.0 - '@nestjs/platform-fastify@11.1.18': - resolution: {integrity: sha512-iJtbqQz51k7Z1vOTUEHO1mU8PsDO1WdgPSJ/6CuXBnazkrkePXoszhefFaPwJreBVn35GE3WTd/6ou7bFwnhmA==} + '@nestjs/platform-fastify@11.1.19': + resolution: {integrity: sha512-PdldJPw+xu8JM7VNE2FY+ty+qoxDMW7326h/z0MtfZvKj84FE6zuqpcSXen1CYjtyP8og+x/5XrJbKKKDNabtQ==} peerDependencies: '@fastify/static': ^8.0.0 || ^9.0.0 '@fastify/view': ^10.0.0 || ^11.0.0 @@ -2953,15 +2963,15 @@ packages: '@fastify/view': optional: true - '@nestjs/platform-socket.io@11.1.18': - resolution: {integrity: sha512-DiFRpMIdFaHqZQFwqLqGHMdNurrKVkRkMHxIrecjooPHJNNIMgrbpYZ+oJW8hpwifUyZUL4r4uXXRy4+yFEMjA==} + '@nestjs/platform-socket.io@11.1.19': + resolution: {integrity: sha512-gu1nPIEaP5Qjjg/Cl8wXyvwGpdZGzgbtK4KcH65YRAA+GTKUkIHb4BNpLJ27Ymq/wqLJKNEbCjajfzD0BEjMGA==} peerDependencies: '@nestjs/common': ^11.0.0 '@nestjs/websockets': ^11.0.0 rxjs: ^7.1.0 - '@nestjs/schedule@6.1.1': - resolution: {integrity: sha512-kQl1RRgi02GJ0uaUGCrXHCcwISsCsJDciCKe38ykJZgnAeeoeVWs8luWtBo4AqAAXm4nS5K8RlV0smHUJ4+2FA==} + '@nestjs/schedule@6.1.3': + resolution: {integrity: sha512-RflMFOpR16Dwd1jAUbeB4mfGTCh65fvEdL4mSjQPJChpkRGRjIXjb+6YQcK2faQrVT60c9DmLmoVR7/ONCtuYQ==} peerDependencies: '@nestjs/common': ^10.0.0 || ^11.0.0 '@nestjs/core': ^10.0.0 || ^11.0.0 @@ -3019,8 +3029,8 @@ packages: typeorm: optional: true - '@nestjs/testing@11.1.18': - resolution: {integrity: sha512-frzwNlpBgtAzI3hp/qo57DZoRO4RMTH1wST3QUYEhRTHyfPkLpzkWz3jV/mhApXjD0yT56Ptlzn6zuYPLh87Lw==} + '@nestjs/testing@11.1.19': + resolution: {integrity: sha512-/UFNWXvPEdu4v4DlC5oWLbGKmD27LehLK06b8oLzs6D6lf4vAQTdST8LRAXBadyMUQnVEQWMuBo3CtAVtlfXtQ==} peerDependencies: '@nestjs/common': ^11.0.0 '@nestjs/core': ^11.0.0 @@ -3039,8 +3049,8 @@ packages: '@nestjs/core': ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 reflect-metadata: ^0.1.13 || ^0.2.0 - '@nestjs/websockets@11.1.18': - resolution: {integrity: sha512-HLO/QGlJoJaMMDphgjbcIwW7/8EA8nnFQjf+qPvA+wWLLfPKoiFPUezc5m9YgN2A7jmzwo6YmEAXeHyqO9tvTw==} + '@nestjs/websockets@11.1.19': + resolution: {integrity: sha512-2qo8jtIwwwgkqAI1BtnJ02EaFLrRkKA39eYXS8IhZCHilhBHCWdjnJ5cLcFq4oF+s+KZ7LcLGD/3stxJy8ijzg==} peerDependencies: '@nestjs/common': ^11.0.0 '@nestjs/core': ^11.0.0 @@ -3223,11 +3233,11 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@posthog/core@1.24.1': - resolution: {integrity: sha512-e8AciAnc6MRFws89ux8lJKFAaI03yEon0ASDoUO7yS91FVqbUGXYekObUUR3LHplcg+pmyiJBI0jolY0SFbGRA==} + '@posthog/core@1.26.0': + resolution: {integrity: sha512-q6pSkW7V9RC3rIXjJBo7IBXOH2KPJEh8o+xIcSqw7QD4vq7OYVzTJfUIvkD38+sm54RG/61/3QaPdpQZkDnOyg==} - '@posthog/types@1.363.1': - resolution: {integrity: sha512-bFYk5XHgYEfVhQU0AwkG9MbMqq9QRbKDDJxOtYWGJ6Uw+/nLRNs/ZydXy3aMt0ldIdkNzZq+qaJ/p2Jg0+mP8g==} + '@posthog/types@1.370.0': + resolution: {integrity: sha512-Hcan3j0L1JZwyaoi8SvbZk41phzHpj5u3/BRn0dFVBlfkbvfhkgXHPETKIZP5CPzjrotOXRLYI4LNRDHp28VsA==} '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -5819,8 +5829,8 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - bullmq@5.71.0: - resolution: {integrity: sha512-aeNWh4drsafSKnAJeiNH/nZP/5O8ZdtdMbnOPZmpjXj7NZUP5YC901U3bIH41iZValm7d1i3c34ojv7q31m30w==} + bullmq@5.76.0: + resolution: {integrity: sha512-gVknzNL7wr3tsDQEf/CL6tHpi++eOWqsLN/s0hETgQmPy6GFVv6aKUQ8yvrbdTbeorC+hbbsLdyqaPD2eLAGRA==} bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} @@ -6541,8 +6551,8 @@ packages: resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} engines: {node: '>= 4'} - dompurify@3.3.3: - resolution: {integrity: sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==} + dompurify@3.4.1: + resolution: {integrity: sha512-JahakDAIg1gyOm7dlgWSDjV4n7Ip2PKR55NIT6jrMfIgLFgWo81vdr1/QGqWtFNRqXP9UV71oVePtjqS2ebnPw==} domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} @@ -6563,14 +6573,14 @@ packages: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} - dotenv@17.2.3: - resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} - engines: {node: '>=12'} - dotenv@17.2.4: resolution: {integrity: sha512-mudtfb4zRB4bVvdj0xRo+e6duH1csJRM8IukBqfTRvHotn9+LBXB8ynAidP9zHqoRC/fsllXgk4kCKlR21fIhw==} engines: {node: '>=12'} + dotenv@17.4.1: + resolution: {integrity: sha512-k8DaKGP6r1G30Lx8V4+pCsLzKr8vLmV2paqEj1Y55GdAgJuIqpRp5FfajGF8KtwMxCz9qJc6wUIJnm053d/WCw==} + engines: {node: '>=12'} + duck@0.1.12: resolution: {integrity: sha512-wkctla1O6VfP89gQ+J/yDesM0S7B7XLXjKGzXxMDVFg7uEn706niAtyYovKbyq1oT9YwDcly721/iUWoc8MVRg==} @@ -6626,10 +6636,6 @@ packages: resolution: {integrity: sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==} engines: {node: '>=10.2.0'} - enhanced-resolve@5.19.0: - resolution: {integrity: sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==} - engines: {node: '>=10.13.0'} - enhanced-resolve@5.20.1: resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} engines: {node: '>=10.13.0'} @@ -6927,8 +6933,8 @@ packages: fastify-plugin@5.1.0: resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} - fastify@5.8.3: - resolution: {integrity: sha512-XJXpRQ41+rsJ/GLeP9vyDC+fBXilcTlEXokMSexkdEkla4uf7ZQNaI5xl3el+kW5TZQulqYxLr659ey/KX7XmQ==} + fastify@5.8.5: + resolution: {integrity: sha512-Yqptv59pQzPgQUSIm87hMqHJmdkb1+GPxdE6vW6FRyVE9G86mt7rOghitiU4JHRaTyDUk9pfeKmDeu70lAwM4Q==} fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -7236,8 +7242,8 @@ packages: hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - hono@4.12.12: - resolution: {integrity: sha512-p1JfQMKaceuCbpJKAPKVqyqviZdS0eUxH9v82oWo1kb9xjQ5wA6iP3FNVAPDFlz5/p7d45lO+BpSk1tuSZMF4Q==} + hono@4.12.14: + resolution: {integrity: sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==} engines: {node: '>=16.9.0'} hookified@1.15.1: @@ -7266,10 +7272,6 @@ packages: htmlparser2@8.0.2: resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} - http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -7373,10 +7375,6 @@ packages: resolution: {integrity: sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==} engines: {node: '>=12.22.0'} - ioredis@5.9.3: - resolution: {integrity: sha512-VI5tMCdeoxZWU5vjHWsiE/Su76JGhBvWF1MJnV9ZtGltHk9BmD48oDq8Tj8haZ85aceXZMxLNDQZRVo5QKNgXA==} - engines: {node: '>=12.22.0'} - ip-address@10.1.0: resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} engines: {node: '>= 12'} @@ -8023,8 +8021,8 @@ packages: resolution: {integrity: sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==} engines: {node: '>=20.10.0', npm: '>=10.2.3'} - langsmith@0.5.18: - resolution: {integrity: sha512-3zuZUWffTHQ+73EAwnodADtf534VNEZUpXr9jC12qyG8/IQuJET7PRsCpTb9wX2lmBspakwLUpqpj3tNm/0bVA==} + langsmith@0.5.19: + resolution: {integrity: sha512-5tFoETuFMvGkbPGsINNlIE4Ab86CsPhdPOQZCGwNt/NX0h5NDKQLKOWS/G2XcRUBOQl4mCNbrayUvUTWaIRsCg==} peerDependencies: '@opentelemetry/api': '*' '@opentelemetry/exporter-trace-otlp-proto': '*' @@ -9038,8 +9036,8 @@ packages: resolution: {integrity: sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==} engines: {node: '>=12'} - posthog-js@1.363.1: - resolution: {integrity: sha512-iaDtRxCs/FiB+RXe83uo7RZXgpLlyB6qFoNHl3bNMgRCgrPI2nkzx2m9Va1l30HHl/zA1kPOXSy2/tZC5Ql5kg==} + posthog-js@1.370.0: + resolution: {integrity: sha512-0PQCUO6EGbXaOPgXYrcafrXa9B13nDaGc91xCiuwNPK80oovqTmeHfNUNCv1r+xCpEoxw3L1FyBuuLCt5Zz7rg==} postmark@4.0.7: resolution: {integrity: sha512-DjNniUl1XNCGUKhCR98ePd5gv16rlUAVKKaU9TUqnE3hDSqfT9XDulu1idjagQmdyGscqnRtXk/puAEiYMeevg==} @@ -9754,10 +9752,6 @@ packages: standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -10450,8 +10444,8 @@ packages: resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} engines: {node: '>=10.13.0'} - webpack@5.105.4: - resolution: {integrity: sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==} + webpack@5.106.0: + resolution: {integrity: sha512-Pkx5joZ9RrdgO5LBkyX1L2ZAJeK/Taz3vqZ9CbcP0wS5LEMx5QkKsEwLl29QJfihZ+DKRBFldzy1O30pJ1MDpA==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -10776,10 +10770,21 @@ snapshots: optionalDependencies: chokidar: 4.0.3 - '@angular-devkit/schematics-cli@19.2.23(@types/node@25.5.0)(chokidar@4.0.3)': + '@angular-devkit/core@19.2.24(chokidar@4.0.3)': dependencies: - '@angular-devkit/core': 19.2.23(chokidar@4.0.3) - '@angular-devkit/schematics': 19.2.23(chokidar@4.0.3) + ajv: 8.18.0 + ajv-formats: 3.0.1(ajv@8.18.0) + jsonc-parser: 3.3.1 + picomatch: 4.0.4 + rxjs: 7.8.1 + source-map: 0.7.4 + optionalDependencies: + chokidar: 4.0.3 + + '@angular-devkit/schematics-cli@19.2.24(@types/node@25.5.0)(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.24(chokidar@4.0.3) '@inquirer/prompts': 7.3.2(@types/node@25.5.0) ansi-colors: 4.1.3 symbol-observable: 4.0.0 @@ -10798,6 +10803,16 @@ snapshots: transitivePeerDependencies: - chokidar + '@angular-devkit/schematics@19.2.24(chokidar@4.0.3)': + dependencies: + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + jsonc-parser: 3.3.1 + magic-string: 0.30.17 + ora: 5.4.1 + rxjs: 7.8.1 + transitivePeerDependencies: + - chokidar + '@antfu/install-pkg@1.1.0': dependencies: package-manager-detector: 1.3.0 @@ -12496,7 +12511,7 @@ snapshots: dependencies: dequal: 2.0.3 - '@fastify/multipart@9.4.0': + '@fastify/multipart@10.0.0': dependencies: '@fastify/busboy': 3.1.1 '@fastify/deepmerge': 3.1.0 @@ -12514,10 +12529,10 @@ snapshots: '@lukeed/ms': 2.0.2 escape-html: 1.0.3 fast-decode-uri-component: 1.0.1 - http-errors: 2.0.0 + http-errors: 2.0.1 mime: 3.0.0 - '@fastify/static@9.0.0': + '@fastify/static@9.1.3': dependencies: '@fastify/accept-negotiator': 2.0.1 '@fastify/send': 4.1.0 @@ -12594,9 +12609,9 @@ snapshots: y-prosemirror: 1.3.7(prosemirror-model@1.25.1)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30) yjs: 13.6.30 - '@hono/node-server@1.19.13(hono@4.12.12)': + '@hono/node-server@1.19.13(hono@4.12.14)': dependencies: - hono: 4.12.12 + hono: 4.12.14 '@humanfs/core@0.19.1': {} @@ -12759,8 +12774,6 @@ snapshots: optionalDependencies: '@types/node': 25.5.0 - '@ioredis/commands@1.5.0': {} - '@ioredis/commands@1.5.1': {} '@istanbuljs/load-nyc-config@1.1.0': @@ -13027,7 +13040,7 @@ snapshots: camelcase: 6.3.0 decamelize: 1.2.0 js-tiktoken: 1.0.21 - langsmith: 0.5.18(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0) + langsmith: 0.5.19(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0) mustache: 4.2.0 p-queue: 6.6.2 uuid: 11.1.0 @@ -13123,7 +13136,7 @@ snapshots: '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6)': dependencies: - '@hono/node-server': 1.19.13(hono@4.12.12) + '@hono/node-server': 1.19.13(hono@4.12.14) ajv: 8.18.0 ajv-formats: 3.0.1(ajv@8.18.0) content-type: 1.0.5 @@ -13133,7 +13146,7 @@ snapshots: eventsource-parser: 3.0.6 express: 5.2.1 express-rate-limit: 8.2.2(express@5.2.1) - hono: 4.12.12 + hono: 4.12.14 jose: 6.1.3 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -13231,63 +13244,63 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@nest-lab/throttler-storage-redis@1.2.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(@nestjs/throttler@6.5.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2))(ioredis@5.10.1)(reflect-metadata@0.2.2)': + '@nest-lab/throttler-storage-redis@1.2.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(@nestjs/throttler@6.5.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2))(ioredis@5.10.1)(reflect-metadata@0.2.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/throttler': 6.5.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/throttler': 6.5.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2) ioredis: 5.10.1 reflect-metadata: 0.2.2 tslib: 2.8.1 - '@nestjs-labs/nestjs-ioredis@11.0.4(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(ioredis@5.10.1)': + '@nestjs-labs/nestjs-ioredis@11.0.4(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(ioredis@5.10.1)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) ioredis: 5.10.1 tslib: 2.8.1 - '@nestjs/bull-shared@11.0.4(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)': + '@nestjs/bull-shared@11.0.4(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) tslib: 2.8.1 - '@nestjs/bullmq@11.0.4(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(bullmq@5.71.0)': + '@nestjs/bullmq@11.0.4(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(bullmq@5.76.0)': dependencies: - '@nestjs/bull-shared': 11.0.4(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18) - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) - bullmq: 5.71.0 + '@nestjs/bull-shared': 11.0.4(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) + bullmq: 5.76.0 tslib: 2.8.1 - '@nestjs/cache-manager@3.1.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(cache-manager@7.2.8)(keyv@5.6.0)(rxjs@7.8.2)': + '@nestjs/cache-manager@3.1.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(cache-manager@7.2.8)(keyv@5.6.0)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) cache-manager: 7.2.8 keyv: 5.6.0 rxjs: 7.8.2 - '@nestjs/cli@11.0.18(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@25.5.0)': + '@nestjs/cli@11.0.21(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@25.5.0)': dependencies: - '@angular-devkit/core': 19.2.23(chokidar@4.0.3) - '@angular-devkit/schematics': 19.2.23(chokidar@4.0.3) - '@angular-devkit/schematics-cli': 19.2.23(@types/node@25.5.0)(chokidar@4.0.3) + '@angular-devkit/core': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics': 19.2.24(chokidar@4.0.3) + '@angular-devkit/schematics-cli': 19.2.24(@types/node@25.5.0)(chokidar@4.0.3) '@inquirer/prompts': 7.10.1(@types/node@25.5.0) '@nestjs/schematics': 11.0.10(chokidar@4.0.3)(typescript@5.9.3) ansis: 4.2.0 chokidar: 4.0.3 cli-table3: 0.6.5 commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5))) + fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5))) glob: 13.0.6 node-emoji: 1.11.0 ora: 5.4.1 tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.2.0 typescript: 5.9.3 - webpack: 5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5)) + webpack: 5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5)) webpack-node-externals: 3.0.0 optionalDependencies: '@swc/core': 1.5.25(@swc/helpers@0.5.5) @@ -13297,7 +13310,7 @@ snapshots: - uglify-js - webpack-cli - '@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: file-type: 21.3.4 iterare: 1.2.1 @@ -13312,17 +13325,17 @@ snapshots: transitivePeerDependencies: - supports-color - '@nestjs/config@4.0.3(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2)': + '@nestjs/config@4.0.4(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - dotenv: 17.2.3 + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + dotenv: 17.4.1 dotenv-expand: 12.0.3 lodash: 4.18.1 rxjs: 7.8.2 - '@nestjs/core@11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/core@11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nuxt/opencollective': 0.4.1 fast-safe-stringify: 2.1.1 iterare: 1.2.1 @@ -13332,41 +13345,41 @@ snapshots: tslib: 2.8.1 uid: 2.0.2 optionalDependencies: - '@nestjs/websockets': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(@nestjs/platform-socket.io@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/websockets': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(@nestjs/platform-socket.io@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/event-emitter@3.0.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)': + '@nestjs/event-emitter@3.0.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) eventemitter2: 6.4.9 - '@nestjs/jwt@11.0.2(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))': + '@nestjs/jwt@11.0.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@types/jsonwebtoken': 9.0.10 jsonwebtoken: 9.0.3 - '@nestjs/mapped-types@2.1.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)': + '@nestjs/mapped-types@2.1.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) reflect-metadata: 0.2.2 optionalDependencies: class-transformer: 0.5.1 class-validator: 0.15.1 - '@nestjs/passport@11.0.5(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0)': + '@nestjs/passport@11.0.5(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(passport@0.7.0)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) passport: 0.7.0 - '@nestjs/platform-fastify@11.1.18(@fastify/static@9.0.0)(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)': + '@nestjs/platform-fastify@11.1.19(@fastify/static@9.1.3)(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)': dependencies: '@fastify/cors': 11.2.0 '@fastify/formbody': 8.0.2 - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) fast-querystring: 1.1.2 - fastify: 5.8.3 + fastify: 5.8.5 fastify-plugin: 5.1.0 find-my-way: 9.5.0 light-my-request: 6.6.0 @@ -13374,12 +13387,12 @@ snapshots: reusify: 1.1.0 tslib: 2.8.1 optionalDependencies: - '@fastify/static': 9.0.0 + '@fastify/static': 9.1.3 - '@nestjs/platform-socket.io@11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(rxjs@7.8.2)': + '@nestjs/platform-socket.io@11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/websockets': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(@nestjs/platform-socket.io@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/websockets': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(@nestjs/platform-socket.io@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) rxjs: 7.8.2 socket.io: 4.8.3 tslib: 2.8.1 @@ -13388,10 +13401,10 @@ snapshots: - supports-color - utf-8-validate - '@nestjs/schedule@6.1.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)': + '@nestjs/schedule@6.1.3(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) cron: 4.4.0 '@nestjs/schematics@11.0.10(chokidar@4.0.3)(typescript@5.9.3)': @@ -13405,38 +13418,38 @@ snapshots: transitivePeerDependencies: - chokidar - '@nestjs/terminus@11.1.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/terminus@11.1.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) boxen: 5.1.2 check-disk-space: 3.4.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 - '@nestjs/testing@11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)': + '@nestjs/testing@11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) tslib: 2.8.1 - '@nestjs/throttler@6.5.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2)': + '@nestjs/throttler@6.5.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) reflect-metadata: 0.2.2 - '@nestjs/websockets@11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(@nestjs/platform-socket.io@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2)': + '@nestjs/websockets@11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(@nestjs/platform-socket.io@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2)': dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) iterare: 1.2.1 object-hash: 3.0.0 reflect-metadata: 0.2.2 rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - '@nestjs/platform-socket.io': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(rxjs@7.8.2) + '@nestjs/platform-socket.io': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(rxjs@7.8.2) '@noble/hashes@1.8.0': {} @@ -13653,11 +13666,9 @@ snapshots: '@pkgr/core@0.2.9': {} - '@posthog/core@1.24.1': - dependencies: - cross-spawn: 7.0.6 + '@posthog/core@1.26.0': {} - '@posthog/types@1.363.1': {} + '@posthog/types@1.370.0': {} '@protobufjs/aspromise@1.1.2': {} @@ -16487,10 +16498,10 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 - bullmq@5.71.0: + bullmq@5.76.0: dependencies: cron-parser: 4.9.0 - ioredis: 5.9.3 + ioredis: 5.10.1 msgpackr: 1.11.5 node-abort-controller: 3.1.1 semver: 7.7.4 @@ -17229,7 +17240,7 @@ snapshots: dependencies: domelementtype: 2.3.0 - dompurify@3.3.3: + dompurify@3.4.1: optionalDependencies: '@types/trusted-types': 2.0.7 @@ -17253,10 +17264,10 @@ snapshots: dotenv@16.4.7: {} - dotenv@17.2.3: {} - dotenv@17.2.4: {} + dotenv@17.4.1: {} + duck@0.1.12: dependencies: underscore: 1.13.8 @@ -17329,11 +17340,6 @@ snapshots: - supports-color - utf-8-validate - enhanced-resolve@5.19.0: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.0 - enhanced-resolve@5.20.1: dependencies: graceful-fs: 4.2.11 @@ -17845,7 +17851,7 @@ snapshots: fastify-plugin@5.1.0: {} - fastify@5.8.3: + fastify@5.8.5: dependencies: '@fastify/ajv-compiler': 4.0.5 '@fastify/error': 4.0.0 @@ -17950,7 +17956,7 @@ snapshots: dependencies: is-callable: 1.2.7 - fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5))): + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5))): dependencies: '@babel/code-frame': 7.27.1 chalk: 4.1.2 @@ -17965,7 +17971,7 @@ snapshots: semver: 7.7.4 tapable: 2.3.0 typescript: 5.9.3 - webpack: 5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5)) + webpack: 5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5)) form-data@4.0.5: dependencies: @@ -18182,7 +18188,7 @@ snapshots: dependencies: react-is: 16.13.1 - hono@4.12.12: {} + hono@4.12.14: {} hookified@1.15.1: {} @@ -18220,14 +18226,6 @@ snapshots: domutils: 3.2.2 entities: 4.5.0 - http-errors@2.0.0: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -18339,20 +18337,6 @@ snapshots: transitivePeerDependencies: - supports-color - ioredis@5.9.3: - dependencies: - '@ioredis/commands': 1.5.0 - cluster-key-slot: 1.1.2 - debug: 4.4.3 - denque: 2.1.0 - lodash.defaults: 4.2.0 - lodash.isarguments: 3.1.0 - redis-errors: 1.2.0 - redis-parser: 3.0.0 - standard-as-callback: 2.1.0 - transitivePeerDependencies: - - supports-color - ip-address@10.1.0: {} ipaddr.js@1.9.1: {} @@ -19176,7 +19160,7 @@ snapshots: vscode-languageserver-textdocument: 1.0.12 vscode-uri: 3.1.0 - langsmith@0.5.18(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0): + langsmith@0.5.19(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0): dependencies: p-queue: 6.6.2 uuid: 10.0.0 @@ -19463,7 +19447,7 @@ snapshots: d3-sankey: 0.12.3 dagre-d3-es: 7.0.14 dayjs: 1.11.19 - dompurify: 3.3.3 + dompurify: 3.4.1 katex: 0.16.40 khroma: 2.1.0 lodash-es: 4.18.1 @@ -19585,23 +19569,23 @@ snapshots: neo-async@2.6.2: {} - nestjs-cls@6.2.0(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2): + nestjs-cls@6.2.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2): dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) reflect-metadata: 0.2.2 rxjs: 7.8.2 - nestjs-kysely@3.1.2(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.18)(kysely@0.28.14)(reflect-metadata@0.2.2): + nestjs-kysely@3.1.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(kysely@0.28.14)(reflect-metadata@0.2.2): dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@nestjs/core': 11.1.18(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.18)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) kysely: 0.28.14 reflect-metadata: 0.2.2 - nestjs-pino@4.6.1(@nestjs/common@11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2): + nestjs-pino@4.6.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2): dependencies: - '@nestjs/common': 11.1.18(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) + '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) pino: 10.1.0 pino-http: 11.0.0 rxjs: 7.8.2 @@ -20203,17 +20187,17 @@ snapshots: postgres@3.4.8: {} - posthog-js@1.363.1: + posthog-js@1.370.0: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.208.0 '@opentelemetry/exporter-logs-otlp-http': 0.208.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.5.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0) - '@posthog/core': 1.24.1 - '@posthog/types': 1.363.1 + '@posthog/core': 1.26.0 + '@posthog/types': 1.370.0 core-js: 3.43.0 - dompurify: 3.3.3 + dompurify: 3.4.1 fflate: 0.4.8 preact: 10.28.3 query-selector-shadow-dom: 1.0.1 @@ -21144,8 +21128,6 @@ snapshots: standard-as-callback@2.1.0: {} - statuses@2.0.1: {} - statuses@2.0.2: {} stdin-discarder@0.2.2: {} @@ -21341,13 +21323,13 @@ snapshots: inherits: 2.0.4 readable-stream: 3.6.2 - terser-webpack-plugin@5.4.0(@swc/core@1.5.25(@swc/helpers@0.5.5))(webpack@5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5))): + terser-webpack-plugin@5.4.0(@swc/core@1.5.25(@swc/helpers@0.5.5))(webpack@5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5))): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 terser: 5.39.0 - webpack: 5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5)) + webpack: 5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5)) optionalDependencies: '@swc/core': 1.5.25(@swc/helpers@0.5.5) @@ -21451,7 +21433,7 @@ snapshots: babel-jest: 30.3.0(@babel/core@7.28.5) jest-util: 30.3.0 - ts-loader@9.5.7(typescript@5.9.3)(webpack@5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5))): + ts-loader@9.5.7(typescript@5.9.3)(webpack@5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5))): dependencies: chalk: 4.1.2 enhanced-resolve: 5.20.1 @@ -21459,7 +21441,7 @@ snapshots: semver: 7.7.4 source-map: 0.7.4 typescript: 5.9.3 - webpack: 5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5)) + webpack: 5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5)) ts-node@10.9.2(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@25.5.0)(typescript@5.9.3): dependencies: @@ -21484,7 +21466,7 @@ snapshots: tsconfig-paths-webpack-plugin@4.2.0: dependencies: chalk: 4.1.2 - enhanced-resolve: 5.19.0 + enhanced-resolve: 5.20.1 tapable: 2.3.0 tsconfig-paths: 4.2.0 @@ -21834,7 +21816,7 @@ snapshots: webpack-sources@3.3.4: {} - webpack@5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5)): + webpack@5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5)): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -21858,7 +21840,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.4.0(@swc/core@1.5.25(@swc/helpers@0.5.5))(webpack@5.105.4(@swc/core@1.5.25(@swc/helpers@0.5.5))) + terser-webpack-plugin: 5.4.0(@swc/core@1.5.25(@swc/helpers@0.5.5))(webpack@5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5))) watchpack: 2.5.1 webpack-sources: 3.3.4 transitivePeerDependencies: From ec83fc82d54bf3728eaa63b20eb4abcb5aef1d97 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:16:26 +0100 Subject: [PATCH 02/63] fix: refactor sanitize --- apps/server/package.json | 5 ++- apps/server/src/common/helpers/utils.spec.ts | Bin 0 -> 3319 bytes apps/server/src/common/helpers/utils.ts | 34 ++++++++++++++---- .../core/attachment/attachment.controller.ts | 15 +++++--- .../integrations/export/export.controller.ts | 19 +++++++--- .../import/services/import.service.ts | 5 ++- pnpm-lock.yaml | 12 +++---- 7 files changed, 64 insertions(+), 26 deletions(-) create mode 100644 apps/server/src/common/helpers/utils.spec.ts diff --git a/apps/server/package.json b/apps/server/package.json index 97af8db7d..c36e9002f 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -110,7 +110,7 @@ "react": "^18.3.1", "reflect-metadata": "^0.2.2", "rxjs": "^7.8.2", - "sanitize-filename-ts": "1.0.2", + "sanitize-filename": "1.6.3", "socket.io": "^4.8.3", "stripe": "^17.7.0", "tlds": "^1.261.0", @@ -165,6 +165,9 @@ "transform": { "^.+\\.(t|j)s$": "ts-jest" }, + "transformIgnorePatterns": [ + "/node_modules/(?!(\\.pnpm/)?(nanoid|uuid|image-dimensions|marked)(@|/))" + ], "collectCoverageFrom": [ "**/*.(t|j)s" ], diff --git a/apps/server/src/common/helpers/utils.spec.ts b/apps/server/src/common/helpers/utils.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..f444e007163fb39fade37d42ba08652ec0621ec3 GIT binary patch literal 3319 zcmc&$&2r;J5ayhx=t{~+24~_m>&q^?6l~!WWZ8n#{#0r#wX7+|l6GbkM}$;y;sGdL zBF~XG*(ae}e;(OM2)W>sr`0pl{q@)1v|1Orac~J%X3DAGaG^Aw$~D3jBqm=&AWllB zv<;pg9K>iNqm~#3yWYVB!ZEyf36}=|Telb!S!xHNb-9r%Jhn2y@xU2CIe{`t!*{fm zfA0dT)`dplE*!b~s}GajXI()-CyI5OjVr=-Eggc&iqgU1 z$R5I{KmV%#&;em>o&a7H7&(l4C>f8&816#e>=}=R%fG|0-}$^o=xR*m;?4WuCRE_B zxsHW3X4^nvkjgA3^dQd5rA9B}O6M}RAQOiM@(fA(I2p>tT5jt>AD^7SXf~fM zS|>{zA_SL{bpfHq#DOHOP;?eC@zWoFLza`N0mfn>jU*LqQ>VkaTXp4KJr=N#)~Tcd zsSV1wqNpi!FF5JIr3fZ39d1w4vO+Tfo5QlIzms55bg8nCqNZYjMLI{hNt*?!DJ&^n z@}dMfVWzk?sftqA@Mg?9L@3R}lS3dNp>8?R-h7w15tVDOdRlfuSAW>{29=3r?(Smm z`nP)Nw@Q14r@khc7{&d+-oei2vmO>hZ4sRa|Qtp*Y zn+Es+t^I|9dTqY{SV|pIs9qb83et*LupQ+JgBHy>{#-~Ve_l96Bpqs;a^1vZ8!vA6 zBPcVMmr;s5sSPEujkl#6^w2Em`8cH+BMg45;3pdM;OI#+#9hKLkZ0gbNyF;66QHiY zha0`z>dQD%Qc0~FHQF5jIPP2DDQeY6Bte5tH?B4V*MqYV!r!<{>w9pkCkTJ1D { + try { + return decodeURIComponent(m); + } catch { + return m; + } + }); + + const sanitized = sanitize(decoded); + if (options.preserveSpaces) { + return sanitized; + } + return sanitized.replace(/ /g, '_').replace(/#/g, '_'); } export function removeAccent(str: string): string { diff --git a/apps/server/src/core/attachment/attachment.controller.ts b/apps/server/src/core/attachment/attachment.controller.ts index 784e527e6..736058191 100644 --- a/apps/server/src/core/attachment/attachment.controller.ts +++ b/apps/server/src/core/attachment/attachment.controller.ts @@ -53,7 +53,6 @@ import { EnvironmentService } from '../../integrations/environment/environment.s import { TokenService } from '../auth/services/token.service'; import { JwtAttachmentPayload, JwtType } from '../auth/dto/jwt-payload'; import * as path from 'path'; -import { sanitize } from 'sanitize-filename-ts'; import { AttachmentInfoDto, RemoveIconDto } from './dto/attachment.dto'; import { PageAccessService } from '../page/page-access/page-access.service'; import { AuditEvent, AuditResource } from '../../common/events/audit-events'; @@ -357,13 +356,19 @@ export class AttachmentController { throw new BadRequestException('Invalid image attachment type'); } - if (!fileName || sanitize(fileName) !== fileName) { + if (!fileName) { throw new BadRequestException('Invalid file name'); } - const filenameWithoutExt = path.basename(fileName, path.extname(fileName)); - if (!isValidUUID(filenameWithoutExt)) { - throw new BadRequestException('Invalid file id'); + const ext = path.extname(fileName); + const filenameWithoutExt = path.basename(fileName, ext); + + if ( + !ext || + !isValidUUID(filenameWithoutExt) || + `${filenameWithoutExt}${ext}` !== fileName + ) { + throw new BadRequestException('Invalid file name'); } const filePath = `${getAttachmentFolderPath(attachmentType, workspace.id)}/${fileName}`; diff --git a/apps/server/src/integrations/export/export.controller.ts b/apps/server/src/integrations/export/export.controller.ts index 1ce3f8c84..140622da7 100644 --- a/apps/server/src/integrations/export/export.controller.ts +++ b/apps/server/src/integrations/export/export.controller.ts @@ -23,9 +23,12 @@ import { SpaceCaslSubject, } from '../../core/casl/interfaces/space-ability.type'; import { FastifyReply } from 'fastify'; -import { sanitize } from 'sanitize-filename-ts'; import { getExportExtension } from './utils'; -import { getMimeType, getPageTitle } from '../../common/helpers'; +import { + getMimeType, + getPageTitle, + sanitizeFileName, +} from '../../common/helpers'; import * as path from 'path'; import { AuditEvent, AuditResource } from '../../common/events/audit-events'; import { @@ -85,7 +88,9 @@ export class ExportController { if (result.type === 'file') { const ext = getExportExtension(dto.format); - const fileName = sanitize(page.title || 'untitled') + ext; + const fileName = + sanitizeFileName(page.title || 'untitled', { preserveSpaces: true }) + + ext; const contentType = getMimeType(path.extname(fileName)); res.headers({ @@ -96,7 +101,9 @@ export class ExportController { res.send(result.content); } else { - const fileName = sanitize(page.title || 'untitled') + '.zip'; + const fileName = + sanitizeFileName(page.title || 'untitled', { preserveSpaces: true }) + + '.zip'; res.headers({ 'Content-Type': 'application/zip', @@ -144,7 +151,9 @@ export class ExportController { 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="' + - encodeURIComponent(sanitize(exportFile.fileName)) + + encodeURIComponent( + sanitizeFileName(exportFile.fileName, { preserveSpaces: true }), + ) + '"', }); diff --git a/apps/server/src/integrations/import/services/import.service.ts b/apps/server/src/integrations/import/services/import.service.ts index 231a6c89a..66c575850 100644 --- a/apps/server/src/integrations/import/services/import.service.ts +++ b/apps/server/src/integrations/import/services/import.service.ts @@ -1,7 +1,6 @@ import { BadRequestException, Injectable, Logger } from '@nestjs/common'; import { PageRepo } from '@docmost/db/repos/page/page.repo'; import { MultipartFile } from '@fastify/multipart'; -import { sanitize } from 'sanitize-filename-ts'; import * as path from 'path'; import { htmlToJson, @@ -53,8 +52,8 @@ export class ImportService { const file = await filePromise; const fileBuffer = await file.toBuffer(); const fileExtension = path.extname(file.filename).toLowerCase(); - const fileName = sanitize( - path.basename(file.filename, fileExtension).slice(0, 255), + const fileName = sanitizeFileName( + path.basename(file.filename, fileExtension), ); const fileContent = fileBuffer.toString(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 56dd6d794..fe7a20429 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -697,9 +697,9 @@ importers: rxjs: specifier: ^7.8.2 version: 7.8.2 - sanitize-filename-ts: - specifier: 1.0.2 - version: 1.0.2 + sanitize-filename: + specifier: 1.6.3 + version: 1.6.3 socket.io: specifier: ^4.8.3 version: 4.8.3 @@ -9570,8 +9570,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sanitize-filename-ts@1.0.2: - resolution: {integrity: sha512-bON2VOJoappmaBHlnxvBNk5R7HkUAsirf5m1M5Kz15uZykDGbHfGPCQNcEQKR8HrQhgh9CmQ6Xe9y71yM9ywkw==} + sanitize-filename@1.6.3: + resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==} sass@1.51.0: resolution: {integrity: sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA==} @@ -20900,7 +20900,7 @@ snapshots: safer-buffer@2.1.2: {} - sanitize-filename-ts@1.0.2: + sanitize-filename@1.6.3: dependencies: truncate-utf8-bytes: 1.0.2 From 8e15b22d8cdbbf511571910555ef90a1728c1a34 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:22:02 +0100 Subject: [PATCH 03/63] package updates --- apps/client/package.json | 8 +- apps/server/package.json | 6 +- apps/server/src/ee | 2 +- package.json | 7 +- pnpm-lock.yaml | 1242 +++++++++++++++++++------------------- 5 files changed, 635 insertions(+), 630 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index bdf222097..b54b86091 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -31,8 +31,8 @@ "emoji-mart": "^5.6.0", "file-saver": "^2.0.5", "highlightjs-sap-abap": "^0.3.0", - "i18next": "^25.10.1", - "i18next-http-backend": "^3.0.2", + "i18next": "25.10.1", + "i18next-http-backend": "3.0.6", "jotai": "^2.18.1", "jotai-optics": "^0.4.0", "js-cookie": "^3.0.5", @@ -42,7 +42,7 @@ "mantine-form-zod-resolver": "^1.3.0", "mermaid": "^11.13.0", "mitt": "^3.0.1", - "posthog-js": "1.370.0", + "posthog-js": "1.372.2", "react": "^18.3.1", "react-arborist": "3.4.0", "react-clear-modal": "^2.0.18", @@ -50,7 +50,7 @@ "react-drawio": "^1.0.7", "react-error-boundary": "^6.1.1", "react-helmet-async": "^3.0.0", - "react-i18next": "^16.5.8", + "react-i18next": "16.5.8", "react-router-dom": "^7.13.1", "semver": "^7.7.4", "socket.io-client": "^4.8.3", diff --git a/apps/server/package.json b/apps/server/package.json index c36e9002f..10a13b61d 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -33,9 +33,9 @@ "@ai-sdk/google": "^3.0.52", "@ai-sdk/openai": "^3.0.47", "@ai-sdk/openai-compatible": "^2.0.37", - "@aws-sdk/client-s3": "3.1014.0", - "@aws-sdk/lib-storage": "3.1014.0", - "@aws-sdk/s3-request-presigner": "3.1014.0", + "@aws-sdk/client-s3": "3.1037.0", + "@aws-sdk/lib-storage": "3.1037.0", + "@aws-sdk/s3-request-presigner": "3.1037.0", "@clickhouse/client": "^1.18.2", "@fastify/cookie": "^11.0.2", "@fastify/multipart": "^10.0.0", diff --git a/apps/server/src/ee b/apps/server/src/ee index e703b8bf4..36d6b68b9 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit e703b8bf47c0d880a1b6acd2b4216167d8e67ff3 +Subproject commit 36d6b68b9307685c362ba9eaf6d1b8e39fee0762 diff --git a/package.json b/package.json index 6d3d97c2d..3e4b7373c 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "ms": "3.0.0-canary.1", "qrcode": "^1.5.4", "rfc6902": "5.2.0", - "uuid": "^13.0.0", + "uuid": "^14.0.0", "y-indexeddb": "^9.0.12", "y-prosemirror": "1.3.7", "yjs": "^13.6.30" @@ -128,11 +128,12 @@ "yaml@>=2.0.0 <2.8.3": "2.8.3", "path-to-regexp@^8": "8.4.0", "brace-expansion@^5": "5.0.5", - "@xmldom/xmldom": "0.8.12", + "@xmldom/xmldom": "0.8.13", "handlebars": "4.7.9", "axios": "1.15.0", "langsmith": "0.5.19", - "follow-redirects": "1.16.0" + "follow-redirects": "1.16.0", + "protobufjs": "7.5.5" }, "neverBuiltDependencies": [] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fe7a20429..73f773844 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,11 +35,12 @@ overrides: yaml@>=2.0.0 <2.8.3: 2.8.3 path-to-regexp@^8: 8.4.0 brace-expansion@^5: 5.0.5 - '@xmldom/xmldom': 0.8.12 + '@xmldom/xmldom': 0.8.13 handlebars: 4.7.9 axios: 1.15.0 langsmith: 0.5.19 follow-redirects: 1.16.0 + protobufjs: 7.5.5 patchedDependencies: react-arborist@3.4.0: @@ -210,8 +211,8 @@ importers: specifier: 5.2.0 version: 5.2.0 uuid: - specifier: ^13.0.0 - version: 13.0.0 + specifier: ^14.0.0 + version: 14.0.0 y-indexeddb: specifier: ^9.0.12 version: 9.0.12(yjs@13.6.30) @@ -310,11 +311,11 @@ importers: specifier: ^0.3.0 version: 0.3.0 i18next: - specifier: ^25.10.1 + specifier: 25.10.1 version: 25.10.1(typescript@5.9.3) i18next-http-backend: - specifier: ^3.0.2 - version: 3.0.2 + specifier: 3.0.6 + version: 3.0.6 jotai: specifier: ^2.18.1 version: 2.18.1(@babel/core@7.28.5)(@babel/template@7.27.2)(@types/react@18.3.12)(react@18.3.1) @@ -343,8 +344,8 @@ importers: specifier: ^3.0.1 version: 3.0.1 posthog-js: - specifier: 1.370.0 - version: 1.370.0 + specifier: 1.372.2 + version: 1.372.2 react: specifier: ^18.3.1 version: 18.3.1 @@ -367,7 +368,7 @@ importers: specifier: ^3.0.0 version: 3.0.0(react@18.3.1) react-i18next: - specifier: ^16.5.8 + specifier: 16.5.8 version: 16.5.8(i18next@25.10.1(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) react-router-dom: specifier: ^7.13.1 @@ -467,14 +468,14 @@ importers: specifier: ^2.0.37 version: 2.0.37(zod@4.3.6) '@aws-sdk/client-s3': - specifier: 3.1014.0 - version: 3.1014.0 + specifier: 3.1037.0 + version: 3.1037.0 '@aws-sdk/lib-storage': - specifier: 3.1014.0 - version: 3.1014.0(@aws-sdk/client-s3@3.1014.0) + specifier: 3.1037.0 + version: 3.1037.0(@aws-sdk/client-s3@3.1037.0) '@aws-sdk/s3-request-presigner': - specifier: 3.1014.0 - version: 3.1014.0 + specifier: 3.1037.0 + version: 3.1037.0 '@clickhouse/client': specifier: ^1.18.2 version: 1.18.2 @@ -931,141 +932,141 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.1014.0': - resolution: {integrity: sha512-0XLrOT4Cm3NEhhiME7l/8LbTXS4KdsbR4dSrY207KNKTcHLLTZ9EXt4ZpgnTfLvWQF3pGP2us4Zi1fYLo0N+Ow==} + '@aws-sdk/client-s3@3.1037.0': + resolution: {integrity: sha512-DBmA1jAW8ST6C4srBxeL1/RLIir/d8WOm4s4mi59mGp6mBktHM59Kwb7GuURaCO60cotuce5zr0sKpMLPcBQyA==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.973.26': - resolution: {integrity: sha512-A/E6n2W42ruU+sfWk+mMUOyVXbsSgGrY3MJ9/0Az5qUdG67y8I6HYzzoAa+e/lzxxl1uCYmEL6BTMi9ZiZnplQ==} + '@aws-sdk/core@3.974.5': + resolution: {integrity: sha512-lMPlYlYfQdNZhlkJgnkmESwrY+hNh3PljmZ+37oAqLNdJ6rnILAwFSyc6B3bJeDOtMORNnMQIej0aTRuOlDyhQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/crc64-nvme@3.972.5': - resolution: {integrity: sha512-2VbTstbjKdT+yKi8m7b3a9CiVac+pL/IY2PHJwsaGkkHmuuqkJZIErPck1h6P3T9ghQMLSdMPyW6Qp7Di5swFg==} + '@aws-sdk/crc64-nvme@3.972.7': + resolution: {integrity: sha512-QUagVVBbC8gODCF6e1aV0mE2TXWB9Opz4k8EJFdNrujUVQm5R4AjJa1mpOqzwOuROBzqJU9zawzig7M96L8Ejg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.24': - resolution: {integrity: sha512-FWg8uFmT6vQM7VuzELzwVo5bzExGaKHdubn0StjgrcU5FvuLExUe+k06kn/40uKv59rYzhez8eFNM4yYE/Yb/w==} + '@aws-sdk/credential-provider-env@3.972.31': + resolution: {integrity: sha512-X/yGB73LmDW/6MdDJGCDzZBUXnM3ys4vs9l+5ZTJmiEswDdP1OjeoAFlFjVGS9o4KB2wZWQ9KOfdVNSSK6Ep3w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.26': - resolution: {integrity: sha512-CY4ppZ+qHYqcXqBVi//sdHST1QK3KzOEiLtpLsc9W2k2vfZPKExGaQIsOwcyvjpjUEolotitmd3mUNY56IwDEA==} + '@aws-sdk/credential-provider-http@3.972.33': + resolution: {integrity: sha512-c0ZF+lwoWVvX5iCaGKL5T/4DnIw88CGqxA0BcBs3U86mIp5EZYPVg+KSPkMXOyokmADvNewiMUfSG2uFwjRp0g==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.972.28': - resolution: {integrity: sha512-wXYvq3+uQcZV7k+bE4yDXCTBdzWTU9x/nMiKBfzInmv6yYK1veMK0AKvRfRBd72nGWYKcL6AxwiPg9z/pYlgpw==} + '@aws-sdk/credential-provider-ini@3.972.35': + resolution: {integrity: sha512-jsU4u/cRkKFLKQS0k918FQ27fzXLG5ENiLWQMYE6581zLeI2hWh04ptlrvZMB3wJT/5d+vSzJk74X1CMFr4y8Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.28': - resolution: {integrity: sha512-ZSTfO6jqUTCysbdBPtEX5OUR//3rbD0lN7jO3sQeS2Gjr/Y+DT6SbIJ0oT2cemNw3UzKu97sNONd1CwNMthuZQ==} + '@aws-sdk/credential-provider-login@3.972.35': + resolution: {integrity: sha512-5oa3j0cA50jPqgNhZ9XdJVopuzUf1klRb28/2MfLYWWiPi9DRVvbrBWT+DidbHTT36520VuXZJahQwR+YgSjrg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.29': - resolution: {integrity: sha512-clSzDcvndpFJAggLDnDb36sPdlZYyEs5Zm6zgZjjUhwsJgSWiWKwFIXUVBcbruidNyBdbpOv2tNDL9sX8y3/0g==} + '@aws-sdk/credential-provider-node@3.972.36': + resolution: {integrity: sha512-4nT2T8Z7vH8KE9EdjEsuIlHpZSlcaK2PrKbQBjuUGU46BCCzF3WvP0u0Uiosni3Ykmmn4rWLVawoOCLotUtCbg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.24': - resolution: {integrity: sha512-Q2k/XLrFXhEztPHqj4SLCNID3hEPdlhh1CDLBpNnM+1L8fq7P+yON9/9M1IGN/dA5W45v44ylERfXtDAlmMNmw==} + '@aws-sdk/credential-provider-process@3.972.31': + resolution: {integrity: sha512-eKeT4MXumpBJsrDLCYcSzIkFPVTFn/es7It2oogp2OhU/ic7P/+xzFpQx9ZhwtXS57Mc5S42BPWi7lHmvs/nYg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.28': - resolution: {integrity: sha512-IoUlmKMLEITFn1SiCTjPfR6KrE799FBo5baWyk/5Ppar2yXZoUdaRqZzJzK6TcJxx450M8m8DbpddRVYlp5R/A==} + '@aws-sdk/credential-provider-sso@3.972.35': + resolution: {integrity: sha512-bCuBdfnj0KGDMdLp6utMTLiJcFN2ek9EgZinxQZZSc3FxjJ/HSqeqab2cjbnoNfy8RM6suDCsRkmVY1izp9I+A==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.28': - resolution: {integrity: sha512-d+6h0SD8GGERzKe27v5rOzNGKOl0D+l0bWJdqrxH8WSQzHzjsQFIAPgIeOTUwBHVsKKwtSxc91K/SWax6XgswQ==} + '@aws-sdk/credential-provider-web-identity@3.972.35': + resolution: {integrity: sha512-swW6Bwvl8lanyEMtZOWE/oR6yqcRQH4HTQZUVsnDVgoXvRjRywpYpLv2BWwjUFyjPrqsdX6FeTkf4tMSe/qFTQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/lib-storage@3.1014.0': - resolution: {integrity: sha512-mM0/YpIEKKQ1hM9n1Q2HhN1ztjk3oNKqFMYP+cZ57FR3XVU4UOw9Npu7gnjfzkNrS7WTDZMe0wCMuDvvtq1Oeg==} + '@aws-sdk/lib-storage@3.1037.0': + resolution: {integrity: sha512-ZFg5Vf4RKS48xTm7DfXTeR0Rvn/Fcu6YFdRygGnvhA+gW3W0WtsRqM1CzkWevYBztdUUAsZqtGbMj9Eu0OaeEg==} engines: {node: '>=20.0.0'} peerDependencies: - '@aws-sdk/client-s3': ^3.1014.0 + '@aws-sdk/client-s3': ^3.1037.0 - '@aws-sdk/middleware-bucket-endpoint@3.972.8': - resolution: {integrity: sha512-WR525Rr2QJSETa9a050isktyWi/4yIGcmY3BQ1kpHqb0LqUglQHCS8R27dTJxxWNZvQ0RVGtEZjTCbZJpyF3Aw==} + '@aws-sdk/middleware-bucket-endpoint@3.972.10': + resolution: {integrity: sha512-Vbc2frZH7wXlMNd+ZZSXUEs/l1Sv8Jj4zUnIfwrYF5lwaLdXHZ9xx4U3rjUcaye3HRhFVc+E5DbBxpRAbB16BA==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-expect-continue@3.972.8': - resolution: {integrity: sha512-5DTBTiotEES1e2jOHAq//zyzCjeMB78lEHd35u15qnrid4Nxm7diqIf9fQQ3Ov0ChH1V3Vvt13thOnrACmfGVQ==} + '@aws-sdk/middleware-expect-continue@3.972.10': + resolution: {integrity: sha512-2Yn0f1Qiq/DjxYR3wfI3LokXnjOhFM7Ssn4LTdFDIxRMCE6I32MAsVnhPX1cUZsuVA9tiZtwwhlSLAtFGxAZlQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.974.6': - resolution: {integrity: sha512-YckB8k1ejbyCg/g36gUMFLNzE4W5cERIa4MtsdO+wpTmJEP0+TB7okWIt7d8TDOvnb7SwvxJ21E4TGOBxFpSWQ==} + '@aws-sdk/middleware-flexible-checksums@3.974.13': + resolution: {integrity: sha512-b6QUe2hQX9XsnCzp6mtzVaERhganDKeb8lmGL6pVhr7rRVH9S9keDFW7uKytuuqmcY5943FixoGqn/QL+sbUBA==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-host-header@3.972.8': - resolution: {integrity: sha512-wAr2REfKsqoKQ+OkNqvOShnBoh+nkPurDKW7uAeVSu6kUECnWlSJiPvnoqxGlfousEY/v9LfS9sNc46hjSYDIQ==} + '@aws-sdk/middleware-host-header@3.972.10': + resolution: {integrity: sha512-IJSsIMeVQ8MMCPbuh1AbltkFhLBLXn7aejzfX5YKT/VLDHn++Dcz8886tXckE+wQssyPUhaXrJhdakO2VilRhg==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-location-constraint@3.972.8': - resolution: {integrity: sha512-KaUoFuoFPziIa98DSQsTPeke1gvGXlc5ZGMhy+b+nLxZ4A7jmJgLzjEF95l8aOQN2T/qlPP3MrAyELm8ExXucw==} + '@aws-sdk/middleware-location-constraint@3.972.10': + resolution: {integrity: sha512-rI3NZvJcEvjoD0+0PI0iUAwlPw2IlSlhyvgBK/3WkKJQE/YiKFedd9dMN2lVacdNxPNhxL/jzQaKQdrGtQagjQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-logger@3.972.8': - resolution: {integrity: sha512-CWl5UCM57WUFaFi5kB7IBY1UmOeLvNZAZ2/OZ5l20ldiJ3TiIz1pC65gYj8X0BCPWkeR1E32mpsCk1L1I4n+lA==} + '@aws-sdk/middleware-logger@3.972.10': + resolution: {integrity: sha512-OOuGvvz1Dm20SjZo5oEBePFqxt5nf8AwkNDSyUHvD9/bfNASmstcYxFAHUowy4n6Io7mWUZ04JURZwSBvyQanQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-recursion-detection@3.972.9': - resolution: {integrity: sha512-/Wt5+CT8dpTFQxEJ9iGy/UGrXr7p2wlIOEHvIr/YcHYByzoLjrqkYqXdJjd9UIgWjv7eqV2HnFJen93UTuwfTQ==} + '@aws-sdk/middleware-recursion-detection@3.972.11': + resolution: {integrity: sha512-+zz6f79Kj9V5qFK2P+D8Ehjnw4AhphAlCAsPjUqEcInA9umtSSKMrHbSagEeOIsDNuvVrH98bjRHcyQukTrhaQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.27': - resolution: {integrity: sha512-gomO6DZwx+1D/9mbCpcqO5tPBqYBK7DtdgjTIjZ4yvfh/S7ETwAPS0XbJgP2JD8Ycr5CwVrEkV1sFtu3ShXeOw==} + '@aws-sdk/middleware-sdk-s3@3.972.34': + resolution: {integrity: sha512-/UL96JKjsjdodcRRMKl99tLQvK6Oi9ptLC9iU1yiTF/ruaDX0mtBBtnLNZDxIZRJOCVOtB49ed1YaTadqygk8Q==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-ssec@3.972.8': - resolution: {integrity: sha512-wqlK0yO/TxEC2UsY9wIlqeeutF6jjLe0f96Pbm40XscTo57nImUk9lBcw0dPgsm0sppFtAkSlDrfpK+pC30Wqw==} + '@aws-sdk/middleware-ssec@3.972.10': + resolution: {integrity: sha512-Gli9A0u8EVVb+5bFDGS/QbSVg28w/wpEidg1ggVcSj65BDTdGR6punsOcVjqdiu1i42WHWo51MCvARPIIz9juw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-user-agent@3.972.28': - resolution: {integrity: sha512-cfWZFlVh7Va9lRay4PN2A9ARFzaBYcA097InT5M2CdRS05ECF5yaz86jET8Wsl2WcyKYEvVr/QNmKtYtafUHtQ==} + '@aws-sdk/middleware-user-agent@3.972.35': + resolution: {integrity: sha512-hOFWNOjVmOocpRlrU04nYxjMOeoe0Obu5AXEuhB8zblMCPl3cG1hdluQCZERRKFyhMQjwZnDbhSHjoMUjetFGw==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.996.18': - resolution: {integrity: sha512-c7ZSIXrESxHKx2Mcopgd8AlzZgoXMr20fkx5ViPWPOLBvmyhw9VwJx/Govg8Ef/IhEon5R9l53Z8fdYSEmp6VA==} + '@aws-sdk/nested-clients@3.997.3': + resolution: {integrity: sha512-SivE6GP228IVgfsrr2c/vqTg95X0Qj39Yw4uIrcddpkUzIltNMoNOR62leHOLhODfjv9K8X2mPTwS69A5kT0nQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/region-config-resolver@3.972.10': - resolution: {integrity: sha512-1dq9ToC6e070QvnVhhbAs3bb5r6cQ10gTVc6cyRV5uvQe7P138TV2uG2i6+Yok4bAkVAcx5AqkTEBUvWEtBlsQ==} + '@aws-sdk/region-config-resolver@3.972.13': + resolution: {integrity: sha512-CvJ2ZIjK/jVD/lbOpowBVElJyC1YxLTIJ13yM0AEo0t2v7swOzGjSA6lJGH+DwZXQhcjUjoYwc8bVYCX5MDr1A==} engines: {node: '>=20.0.0'} - '@aws-sdk/s3-request-presigner@3.1014.0': - resolution: {integrity: sha512-XEcK50lToSoLPrQztKQhONYQW45613H8oEL00mBUd/+OZgk0+3zJ8kSNDsIJioZ3H7Be+yC3CL6a22dZFIKUXQ==} + '@aws-sdk/s3-request-presigner@3.1037.0': + resolution: {integrity: sha512-rZQS8DxrqPYXzOvaoysf6L4fHmgFbndZz3GfUMhlHG1iWmcQqH7v0AGhpjyNBY3cYAX8+CAkOkD4VUrntnHNbQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.996.15': - resolution: {integrity: sha512-Ukw2RpqvaL96CjfH/FgfBmy/ZosHBqoHBCFsN61qGg99F33vpntIVii8aNeh65XuOja73arSduskoa4OJea9RQ==} + '@aws-sdk/signature-v4-multi-region@3.996.22': + resolution: {integrity: sha512-/rXhMXteD+BqhFd0nYprAgcZ/KtU+963uftPqd3tiFcFfooHZINXUGtOmo2SQjRVauCTNqIEzkwuSETdZFqTTA==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1021.0': - resolution: {integrity: sha512-TKY6h9spUk3OLs5v1oAgW9mAeBE3LAGNBwJokLy96wwmd4W2v/tYlXseProyed9ValDj2u1jK/4Rg1T+1NXyJA==} + '@aws-sdk/token-providers@3.1036.0': + resolution: {integrity: sha512-aNSJ6jjDYayxN9ZA1JpycVScX93Lx03kKZ1EXt3DGOTahcWVLJj3oLAlop0xKP+vP2Ga2t49p1tEaMkTbCCaZA==} engines: {node: '>=20.0.0'} - '@aws-sdk/types@3.973.6': - resolution: {integrity: sha512-Atfcy4E++beKtwJHiDln2Nby8W/mam64opFPTiHEqgsthqeydFS1pY+OUlN1ouNOmf8ArPU/6cDS65anOP3KQw==} + '@aws-sdk/types@3.973.8': + resolution: {integrity: sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==} engines: {node: '>=20.0.0'} '@aws-sdk/util-arn-parser@3.972.3': resolution: {integrity: sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-endpoints@3.996.5': - resolution: {integrity: sha512-Uh93L5sXFNbyR5sEPMzUU8tJ++Ku97EY4udmC01nB8Zu+xfBPwpIwJ6F7snqQeq8h2pf+8SGN5/NoytfKgYPIw==} + '@aws-sdk/util-endpoints@3.996.8': + resolution: {integrity: sha512-oOZHcRDihk5iEe5V25NVWg45b3qEA8OpHWVdU/XQh8Zj4heVPAJqWvMphQnU7LkufmUo10EpvFPZuQMiFLJK3g==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-format-url@3.972.8': - resolution: {integrity: sha512-J6DS9oocrgxM8xlUTTmQOuwRF6rnAGEujAN9SAzllcrQmwn5iJ58ogxy3SEhD0Q7JZvlA5jvIXBkpQRqEqlE9A==} + '@aws-sdk/util-format-url@3.972.10': + resolution: {integrity: sha512-DEKiHNJVtNxdyTeQspzY+15Po/kHm6sF0Cs4HV9Q2+lplB63+DrvdeiSoOSdWEWAoO2RcY1veoXVDz2tWxWCgQ==} engines: {node: '>=20.0.0'} '@aws-sdk/util-locate-window@3.535.0': resolution: {integrity: sha512-PHJ3SL6d2jpcgbqdgiPxkXpu7Drc2PYViwxSIqvvMKhDwzSB1W3mMvtpzwKM4IE7zLFodZo0GKjJ9AsoXndXhA==} engines: {node: '>=14.0.0'} - '@aws-sdk/util-user-agent-browser@3.972.8': - resolution: {integrity: sha512-B3KGXJviV2u6Cdw2SDY2aDhoJkVfY/Q/Trwk2CMSkikE1Oi6gRzxhvhIfiRpHfmIsAhV4EA54TVEX8K6CbHbkA==} + '@aws-sdk/util-user-agent-browser@3.972.10': + resolution: {integrity: sha512-FAzqXvfEssGdSIz8ejatan0bOdx1qefBWKF/gWmVBXIP1HkS7v/wjjaqrAGGKvyihrXTXW00/2/1nTJtxpXz7g==} - '@aws-sdk/util-user-agent-node@3.973.14': - resolution: {integrity: sha512-vNSB/DYaPOyujVZBg/zUznH9QC142MaTHVmaFlF7uzzfg3CgT9f/l4C0Yi+vU/tbBhxVcXVB90Oohk5+o+ZbWw==} + '@aws-sdk/util-user-agent-node@3.973.21': + resolution: {integrity: sha512-Av4UHTcAWgdvbN0IP9pbtf4Qa1+6LtJqQdZWj5pLn5J67w0pnJJAZZ+7JPPcj2KN3378zD2JDM9DwJKEyvyMTQ==} engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -1073,8 +1074,8 @@ packages: aws-crt: optional: true - '@aws-sdk/xml-builder@3.972.16': - resolution: {integrity: sha512-iu2pyvaqmeatIJLURLqx9D+4jKAdTH20ntzB6BFwjyN7V960r4jK32mx0Zf7YbtOYAbmbtQfDNuL60ONinyw7A==} + '@aws-sdk/xml-builder@3.972.19': + resolution: {integrity: sha512-Cw8IOMdBUEIl8ZlhRC3Dc/E64D5B5/8JhV6vhPLiPfJwcRC84S6F8aBOIi/N4vR9ZyA4I5Cc0Ateb/9EHaJXeQ==} engines: {node: '>=20.0.0'} '@aws/lambda-invoke-store@0.2.3': @@ -3069,6 +3070,9 @@ packages: resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} engines: {node: '>= 20.19.0'} + '@nodable/entities@2.1.0': + resolution: {integrity: sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==} + '@node-saml/node-saml@5.1.0': resolution: {integrity: sha512-t3cJnZ4aC7HhPZ6MGylGZULvUtBOZ6FzuUndaHGXjmIZHXnLfC/7L8a57O9Q9V7AxJGKAiRM5zu2wNm9EsvQpw==} engines: {node: '>= 18'} @@ -3233,11 +3237,11 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - '@posthog/core@1.26.0': - resolution: {integrity: sha512-q6pSkW7V9RC3rIXjJBo7IBXOH2KPJEh8o+xIcSqw7QD4vq7OYVzTJfUIvkD38+sm54RG/61/3QaPdpQZkDnOyg==} + '@posthog/core@1.27.6': + resolution: {integrity: sha512-FjvgPdORywAjgjtgkZJ2/x9ED52jtOJym/RVldY4Oa7wzmlY49rxZm8gvOlocEnjP90bSbj3ko7qVjXNhftFvA==} - '@posthog/types@1.370.0': - resolution: {integrity: sha512-Hcan3j0L1JZwyaoi8SvbZk41phzHpj5u3/BRn0dFVBlfkbvfhkgXHPETKIZP5CPzjrotOXRLYI4LNRDHp28VsA==} + '@posthog/types@1.372.2': + resolution: {integrity: sha512-dx+WImdDg2NDqaDowTmW+BMNalUfPKngR+g1Iom8ULSav+fGacxexv6fSOl0uSVBwYZsDFe7qNUu0NB/rwGjEw==} '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -4254,10 +4258,6 @@ packages: '@sinonjs/fake-timers@15.1.1': resolution: {integrity: sha512-cO5W33JgAPbOh07tvZjUOJ7oWhtaqGHiZw+11DPbyqh2kHTBc3eF/CjJDeQ4205RLQsX6rxCuYOroFQwl7JDRw==} - '@smithy/abort-controller@4.2.12': - resolution: {integrity: sha512-xolrFw6b+2iYGl6EcOL7IJY71vvyZ0DJ3mcKtpykqPe2uscwtzDZJa1uVQXyP7w9Dd+kGwYnPbMsJrGISKiY/Q==} - engines: {node: '>=18.0.0'} - '@smithy/chunked-blob-reader-native@4.2.3': resolution: {integrity: sha512-jA5k5Udn7Y5717L86h4EIv06wIr3xn8GM1qHRi/Nf31annXcXHJjBKvgztnbn2TxH3xWrPBfgwHsOwZf0UmQWw==} engines: {node: '>=18.0.0'} @@ -4266,56 +4266,56 @@ packages: resolution: {integrity: sha512-St+kVicSyayWQca+I1rGitaOEH6uKgE8IUWoYnnEX26SWdWQcL6LvMSD19Lg+vYHKdT9B2Zuu7rd3i6Wnyb/iw==} engines: {node: '>=18.0.0'} - '@smithy/config-resolver@4.4.13': - resolution: {integrity: sha512-iIzMC5NmOUP6WL6o8iPBjFhUhBZ9pPjpUpQYWMUFQqKyXXzOftbfK8zcQCz/jFV1Psmf05BK5ypx4K2r4Tnwdg==} + '@smithy/config-resolver@4.4.17': + resolution: {integrity: sha512-TzDZcAnhTyAHbXVxWZo7/tEcrIeFq20IBk8So3OLOetWpR8EwY/yEqBMBFaJMeyEiREDq4NfEl+qO3OAUD+vbQ==} engines: {node: '>=18.0.0'} - '@smithy/core@3.23.13': - resolution: {integrity: sha512-J+2TT9D6oGsUVXVEMvz8h2EmdVnkBiy2auCie4aSJMvKlzUtO5hqjEzXhoCUkIMo7gAYjbQcN0g/MMSXEhDs1Q==} + '@smithy/core@3.23.17': + resolution: {integrity: sha512-x7BlLbUFL8NWCGjMF9C+1N5cVCxcPa7g6Tv9B4A2luWx3be3oU8hQ96wIwxe/s7OhIzvoJH73HAUSg5JXVlEtQ==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.2.12': - resolution: {integrity: sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==} + '@smithy/credential-provider-imds@4.2.14': + resolution: {integrity: sha512-Au28zBN48ZAoXdooGUHemuVBrkE+Ie6RPmGNIAJsFqj33Vhb6xAgRifUydZ2aY+M+KaMAETAlKk5NC5h1G7wpg==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-codec@4.2.12': - resolution: {integrity: sha512-FE3bZdEl62ojmy8x4FHqxq2+BuOHlcxiH5vaZ6aqHJr3AIZzwF5jfx8dEiU/X0a8RboyNDjmXjlbr8AdEyLgiA==} + '@smithy/eventstream-codec@4.2.14': + resolution: {integrity: sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-browser@4.2.12': - resolution: {integrity: sha512-XUSuMxlTxV5pp4VpqZf6Sa3vT/Q75FVkLSpSSE3KkWBvAQWeuWt1msTv8fJfgA4/jcJhrbrbMzN1AC/hvPmm5A==} + '@smithy/eventstream-serde-browser@4.2.14': + resolution: {integrity: sha512-8IelTCtTctWRbb+0Dcy+C0aICh1qa0qWXqgjcXDmMuCvPJRnv26hiDZoAau2ILOniki65mCPKqOQs/BaWvO4CQ==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-config-resolver@4.3.12': - resolution: {integrity: sha512-7epsAZ3QvfHkngz6RXQYseyZYHlmWXSTPOfPmXkiS+zA6TBNo1awUaMFL9vxyXlGdoELmCZyZe1nQE+imbmV+Q==} + '@smithy/eventstream-serde-config-resolver@4.3.14': + resolution: {integrity: sha512-sqHiHpYRYo3FJlaIxD1J8PhbcmJAm7IuM16mVnwSkCToD7g00IBZzKuiLNMGmftULmEUX6/UAz8/NN5uMP8bVA==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-node@4.2.12': - resolution: {integrity: sha512-D1pFuExo31854eAvg89KMn9Oab/wEeJR6Buy32B49A9Ogdtx5fwZPqBHUlDzaCDpycTFk2+fSQgX689Qsk7UGA==} + '@smithy/eventstream-serde-node@4.2.14': + resolution: {integrity: sha512-Ht/8BuGlKfFTy0H3+8eEu0vdpwGztCnaLLXtpXNdQqiR7Hj4vFScU3T436vRAjATglOIPjJXronY+1WxxNLSiw==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-universal@4.2.12': - resolution: {integrity: sha512-+yNuTiyBACxOJUTvbsNsSOfH9G9oKbaJE1lNL3YHpGcuucl6rPZMi3nrpehpVOVR2E07YqFFmtwpImtpzlouHQ==} + '@smithy/eventstream-serde-universal@4.2.14': + resolution: {integrity: sha512-lWyt4T2XQZUZgK3tQ3Wn0w3XBvZsK/vjTuJl6bXbnGZBHH0ZUSONTYiK9TgjTTzU54xQr3DRFwpjmhp0oLm3gg==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.3.15': - resolution: {integrity: sha512-T4jFU5N/yiIfrtrsb9uOQn7RdELdM/7HbyLNr6uO/mpkj1ctiVs7CihVr51w4LyQlXWDpXFn4BElf1WmQvZu/A==} + '@smithy/fetch-http-handler@5.3.17': + resolution: {integrity: sha512-bXOvQzaSm6MnmLaWA1elgfQcAtN4UP3vXqV97bHuoOrHQOJiLT3ds6o9eo5bqd0TJfRFpzdGnDQdW3FACiAVdw==} engines: {node: '>=18.0.0'} - '@smithy/hash-blob-browser@4.2.13': - resolution: {integrity: sha512-YrF4zWKh+ghLuquldj6e/RzE3xZYL8wIPfkt0MqCRphVICjyyjH8OwKD7LLlKpVEbk4FLizFfC1+gwK6XQdR3g==} + '@smithy/hash-blob-browser@4.2.15': + resolution: {integrity: sha512-0PJ4Al3fg2nM4qKrAIxyNcApgqHAXcBkN8FeizOz69z0rb26uZ6lMESYtxegaTlXB5Hj84JfwMPavMrwDMjucA==} engines: {node: '>=18.0.0'} - '@smithy/hash-node@4.2.12': - resolution: {integrity: sha512-QhBYbGrbxTkZ43QoTPrK72DoYviDeg6YKDrHTMJbbC+A0sml3kSjzFtXP7BtbyJnXojLfTQldGdUR0RGD8dA3w==} + '@smithy/hash-node@4.2.14': + resolution: {integrity: sha512-8ZBDY2DD4wr+GGjTpPtiglEsqr0lUP+KHqgZcWczFf6qeZ/YRjMIOoQWVQlmwu7EtxKTd8YXD8lblmYcpBIA1g==} engines: {node: '>=18.0.0'} - '@smithy/hash-stream-node@4.2.12': - resolution: {integrity: sha512-O3YbmGExeafuM/kP7Y8r6+1y0hIh3/zn6GROx0uNlB54K9oihAL75Qtc+jFfLNliTi6pxOAYZrRKD9A7iA6UFw==} + '@smithy/hash-stream-node@4.2.14': + resolution: {integrity: sha512-tw4GANWkZPb6+BdD4Fgucqzey2+r73Z/GRo9zklsCdwrnxxumUV83ZIaBDdudV4Ylazw3EPTiJZhpX42105ruQ==} engines: {node: '>=18.0.0'} - '@smithy/invalid-dependency@4.2.12': - resolution: {integrity: sha512-/4F1zb7Z8LOu1PalTdESFHR0RbPwHd3FcaG1sI3UEIriQTWakysgJr65lc1jj6QY5ye7aFsisajotH6UhWfm/g==} + '@smithy/invalid-dependency@4.2.14': + resolution: {integrity: sha512-c21qJiTSb25xvvOp+H2TNZzPCngrvl5vIPqPB8zQ/DmJF4QWXO19x1dWfMJZ6wZuuWUPPm0gV8C0cU3+ifcWuw==} engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': @@ -4326,76 +4326,76 @@ packages: resolution: {integrity: sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==} engines: {node: '>=18.0.0'} - '@smithy/md5-js@4.2.12': - resolution: {integrity: sha512-W/oIpHCpWU2+iAkfZYyGWE+qkpuf3vEXHLxQQDx9FPNZTTdnul0dZ2d/gUFrtQ5je1G2kp4cjG0/24YueG2LbQ==} + '@smithy/md5-js@4.2.14': + resolution: {integrity: sha512-V2v0vx+h0iUSNG1Alt+GNBMSLGCrl9iVsdd+Ap67HPM9PN479x12V8LkuMoKImNZxn3MXeuyUjls+/7ZACZghA==} engines: {node: '>=18.0.0'} - '@smithy/middleware-content-length@4.2.12': - resolution: {integrity: sha512-YE58Yz+cvFInWI/wOTrB+DbvUVz/pLn5mC5MvOV4fdRUc6qGwygyngcucRQjAhiCEbmfLOXX0gntSIcgMvAjmA==} + '@smithy/middleware-content-length@4.2.14': + resolution: {integrity: sha512-xhHq7fX4/3lv5NHxLUk3OeEvl0xZ+Ek3qIbWaCL4f9JwgDZEclPBElljaZCAItdGPQl/kSM4LPMOpy1MYgprpw==} engines: {node: '>=18.0.0'} - '@smithy/middleware-endpoint@4.4.28': - resolution: {integrity: sha512-p1gfYpi91CHcs5cBq982UlGlDrxoYUX6XdHSo91cQ2KFuz6QloHosO7Jc60pJiVmkWrKOV8kFYlGFFbQ2WUKKQ==} + '@smithy/middleware-endpoint@4.4.32': + resolution: {integrity: sha512-ZZkgyjnJppiZbIm6Qbx92pbXYi1uzenIvGhBSCDlc7NwuAkiqSgS75j1czAD25ZLs2FjMjYy1q7gyRVWG6JA0Q==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.4.46': - resolution: {integrity: sha512-SpvWNNOPOrKQGUqZbEPO+es+FRXMWvIyzUKUOYdDgdlA6BdZj/R58p4umoQ76c2oJC44PiM7mKizyyex1IJzow==} + '@smithy/middleware-retry@4.5.5': + resolution: {integrity: sha512-wnYOpB5vATFKWrY2Z9Alb0KhjZI6AbzU6Fbz3Hq2GnURdRYWB4q+qWivQtSTwXcmWUA3MZ6krfwL6Cq5MAbxsA==} engines: {node: '>=18.0.0'} - '@smithy/middleware-serde@4.2.16': - resolution: {integrity: sha512-beqfV+RZ9RSv+sQqor3xroUUYgRFCGRw6niGstPG8zO9LgTl0B0MCucxjmrH/2WwksQN7UUgI7KNANoZv+KALA==} + '@smithy/middleware-serde@4.2.20': + resolution: {integrity: sha512-Lx9JMO9vArPtiChE3wbEZ5akMIDQpWQtlu90lhACQmNOXcGXRbaDywMHDzuDZ2OkZzP+9wQfZi3YJT9F67zTQQ==} engines: {node: '>=18.0.0'} - '@smithy/middleware-stack@4.2.12': - resolution: {integrity: sha512-kruC5gRHwsCOuyCd4ouQxYjgRAym2uDlCvQ5acuMtRrcdfg7mFBg6blaxcJ09STpt3ziEkis6bhg1uwrWU7txw==} + '@smithy/middleware-stack@4.2.14': + resolution: {integrity: sha512-2dvkUKLuFdKsCRmOE4Mn63co0Djtsm+JMh0bYZQupN1pJwMeE8FmQmRLLzzEMN0dnNi7CDCYYH8F0EVwWiPBeA==} engines: {node: '>=18.0.0'} - '@smithy/node-config-provider@4.3.12': - resolution: {integrity: sha512-tr2oKX2xMcO+rBOjobSwVAkV05SIfUKz8iI53rzxEmgW3GOOPOv0UioSDk+J8OpRQnpnhsO3Af6IEBabQBVmiw==} + '@smithy/node-config-provider@4.3.14': + resolution: {integrity: sha512-S+gFjyo/weSVL0P1b9Ts8C/CwIfNCgUPikk3sl6QVsfE/uUuO+QsF+NsE/JkpvWqqyz1wg7HFdiaZuj5CoBMRg==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.5.1': - resolution: {integrity: sha512-ejjxdAXjkPIs9lyYyVutOGNOraqUE9v/NjGMKwwFrfOM354wfSD8lmlj8hVwUzQmlLLF4+udhfCX9Exnbmvfzw==} + '@smithy/node-http-handler@4.6.1': + resolution: {integrity: sha512-iB+orM4x3xrr57X3YaXazfKnntl0LHlZB1kcXSGzMV1Tt0+YwEjGlbjk/44qEGtBzXAz6yFDzkYTKSV6Pj2HUg==} engines: {node: '>=18.0.0'} - '@smithy/property-provider@4.2.12': - resolution: {integrity: sha512-jqve46eYU1v7pZ5BM+fmkbq3DerkSluPr5EhvOcHxygxzD05ByDRppRwRPPpFrsFo5yDtCYLKu+kreHKVrvc7A==} + '@smithy/property-provider@4.2.14': + resolution: {integrity: sha512-WuM31CgfsnQ/10i7NYr0PyxqknD72Y5uMfUMVSniPjbEPceiTErb4eIqJQ+pdxNEAUEWrewrGjIRjVbVHsxZiQ==} engines: {node: '>=18.0.0'} - '@smithy/protocol-http@5.3.12': - resolution: {integrity: sha512-fit0GZK9I1xoRlR4jXmbLhoN0OdEpa96ul8M65XdmXnxXkuMxM0Y8HDT0Fh0Xb4I85MBvBClOzgSrV1X2s1Hxw==} + '@smithy/protocol-http@5.3.14': + resolution: {integrity: sha512-dN5F8kHx8RNU0r+pCwNmFZyz6ChjMkzShy/zup6MtkRmmix4vZzJdW+di7x//b1LiynIev88FM18ie+wwPcQtQ==} engines: {node: '>=18.0.0'} - '@smithy/querystring-builder@4.2.12': - resolution: {integrity: sha512-6wTZjGABQufekycfDGMEB84BgtdOE/rCVTov+EDXQ8NHKTUNIp/j27IliwP7tjIU9LR+sSzyGBOXjeEtVgzCHg==} + '@smithy/querystring-builder@4.2.14': + resolution: {integrity: sha512-XYA5Z0IqTeF+5XDdh4BBmSA0HvbgVZIyv4cmOoUheDNR57K1HgBp9ukUMx3Cr3XpDHHpLBnexPE3LAtDsZkj2A==} engines: {node: '>=18.0.0'} - '@smithy/querystring-parser@4.2.12': - resolution: {integrity: sha512-P2OdvrgiAKpkPNKlKUtWbNZKB1XjPxM086NeVhK+W+wI46pIKdWBe5QyXvhUm3MEcyS/rkLvY8rZzyUdmyDZBw==} + '@smithy/querystring-parser@4.2.14': + resolution: {integrity: sha512-hr+YyqBD23GVvRxGGrcc/oOeNlK3PzT5Fu4dzrDXxzS1LpFiuL2PQQqKPs87M79aW7ziMs+nvB3qdw77SqE7Lw==} engines: {node: '>=18.0.0'} - '@smithy/service-error-classification@4.2.12': - resolution: {integrity: sha512-LlP29oSQN0Tw0b6D0Xo6BIikBswuIiGYbRACy5ujw/JgWSzTdYj46U83ssf6Ux0GyNJVivs2uReU8pt7Eu9okQ==} + '@smithy/service-error-classification@4.3.0': + resolution: {integrity: sha512-9jKsBYQRPR0xBLgc2415RsA5PIcP2sis4oBdN9s0D13cg1B1284mNTjx9Yc+BEERXzuPm5ObktI96OxsKh8E9A==} engines: {node: '>=18.0.0'} - '@smithy/shared-ini-file-loader@4.4.7': - resolution: {integrity: sha512-HrOKWsUb+otTeo1HxVWeEb99t5ER1XrBi/xka2Wv6NVmTbuCUC1dvlrksdvxFtODLBjsC+PHK+fuy2x/7Ynyiw==} + '@smithy/shared-ini-file-loader@4.4.9': + resolution: {integrity: sha512-495/V2I15SHgedSJoDPD23JuSfKAp726ZI1V0wtjB07Wh7q/0tri/0e0DLefZCHgxZonrGKt/OCTpAtP1wE1kQ==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.3.12': - resolution: {integrity: sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==} + '@smithy/signature-v4@5.3.14': + resolution: {integrity: sha512-1D9Y/nmlVjCeSivCbhZ7hgEpmHyY1h0GvpSZt3l0xcD9JjmjVC1CHOozS6+Gh+/ldMH8JuJ6cujObQqfayAVFA==} engines: {node: '>=18.0.0'} - '@smithy/smithy-client@4.12.8': - resolution: {integrity: sha512-aJaAX7vHe5i66smoSSID7t4rKY08PbD8EBU7DOloixvhOozfYWdcSYE4l6/tjkZ0vBZhGjheWzB2mh31sLgCMA==} + '@smithy/smithy-client@4.12.13': + resolution: {integrity: sha512-y/Pcj1V9+qG98gyu1gvftHB7rDpdh+7kIBIggs55yGm3JdtBV8GT8IFF3a1qxZ79QnaJHX9GXzvBG6tAd+czJA==} engines: {node: '>=18.0.0'} - '@smithy/types@4.13.1': - resolution: {integrity: sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==} + '@smithy/types@4.14.1': + resolution: {integrity: sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg==} engines: {node: '>=18.0.0'} - '@smithy/url-parser@4.2.12': - resolution: {integrity: sha512-wOPKPEpso+doCZGIlr+e1lVI6+9VAKfL4kZWFgzVgGWY2hZxshNKod4l2LXS3PRC9otH/JRSjtEHqQ/7eLciRA==} + '@smithy/url-parser@4.2.14': + resolution: {integrity: sha512-p06BiBigJ8bTA3MgnOfCtDUWnAMY0YfedO/GRpmc7p+wg3KW8vbXy1xwSu5ASy0wV7rRYtlfZOIKH4XqfhjSQQ==} engines: {node: '>=18.0.0'} '@smithy/util-base64@4.3.2': @@ -4422,32 +4422,32 @@ packages: resolution: {integrity: sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-browser@4.3.44': - resolution: {integrity: sha512-eZg6XzaCbVr2S5cAErU5eGBDaOVTuTo1I65i4tQcHENRcZ8rMWhQy1DaIYUSLyZjsfXvmCqZrstSMYyGFocvHA==} + '@smithy/util-defaults-mode-browser@4.3.49': + resolution: {integrity: sha512-a5bNrdiONYB/qE2BuKegvUMd/+ZDwdg4vsNuuSzYE8qs2EYAdK9CynL+Rzn29PbPiUqoz/cbpRbcLzD5lEevHw==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.2.48': - resolution: {integrity: sha512-FqOKTlqSaoV3nzO55pMs5NBnZX8EhoI0DGmn9kbYeXWppgHD6dchyuj2HLqp4INJDJbSrj6OFYJkAh/WhSzZPg==} + '@smithy/util-defaults-mode-node@4.2.54': + resolution: {integrity: sha512-g1cvrJvOnzeJgEdf7AE4luI7gp6L8weE0y9a9wQUSGtjb8QRHDbCJYuE4Sy0SD9N8RrnNPFsPltAz/OSoBR9Zw==} engines: {node: '>=18.0.0'} - '@smithy/util-endpoints@3.3.3': - resolution: {integrity: sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==} + '@smithy/util-endpoints@3.4.2': + resolution: {integrity: sha512-a55Tr+3OKld4TTtnT+RhKOQHyPxm3j/xL4OR83WBUhLJaKDS9dnJ7arRMOp3t31dcLhApwG9bgvrRXBHlLdIkg==} engines: {node: '>=18.0.0'} '@smithy/util-hex-encoding@4.2.2': resolution: {integrity: sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==} engines: {node: '>=18.0.0'} - '@smithy/util-middleware@4.2.12': - resolution: {integrity: sha512-Er805uFUOvgc0l8nv0e0su0VFISoxhJ/AwOn3gL2NWNY2LUEldP5WtVcRYSQBcjg0y9NfG8JYrCJaYDpupBHJQ==} + '@smithy/util-middleware@4.2.14': + resolution: {integrity: sha512-1Su2vj9RYNDEv/V+2E+jXkkwGsgR7dc4sfHn9Z7ruzQHJIEni9zzw5CauvRXlFJfmgcqYP8fWa0dkh2Q2YaQyw==} engines: {node: '>=18.0.0'} - '@smithy/util-retry@4.2.13': - resolution: {integrity: sha512-qQQsIvL0MGIbUjeSrg0/VlQ3jGNKyM3/2iU3FPNgy01z+Sp4OvcaxbgIoFOTvB61ZoohtutuOvOcgmhbD0katQ==} + '@smithy/util-retry@4.3.4': + resolution: {integrity: sha512-FY1UQQ1VFmMwiYp1GVS4MeaGD5O0blLNYK0xCRHU+mJgeoH/hSY8Ld8sJWKQ6uznkh14HveRGQJncgPyNl9J+A==} engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.5.21': - resolution: {integrity: sha512-KzSg+7KKywLnkoKejRtIBXDmwBfjGvg1U1i/etkC7XSWUyFCoLno1IohV2c74IzQqdhX5y3uE44r/8/wuK+A7Q==} + '@smithy/util-stream@4.5.25': + resolution: {integrity: sha512-/PFpG4k8Ze8Ei+mMKj3oiPICYekthuzePZMgZbCqMiXIHHf4n2aZ4Ps0aSRShycFTGuj/J6XldmC0x0DwednIA==} engines: {node: '>=18.0.0'} '@smithy/util-uri-escape@4.2.2': @@ -4462,8 +4462,8 @@ packages: resolution: {integrity: sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==} engines: {node: '>=18.0.0'} - '@smithy/util-waiter@4.2.14': - resolution: {integrity: sha512-2zqq5o/oizvMaFUlNiTyZ7dbgYv1a893aGut2uaxtbzTx/VYYnRxWzDHuD/ftgcw94ffenua+ZNLrbqwUYE+Bg==} + '@smithy/util-waiter@4.2.16': + resolution: {integrity: sha512-GtclrKoZ3Lt7jPQ7aTIYKfjY92OgceScftVnkTsG8e1KV8rkvZgN+ny6YSRhd9hxB8rZtwVbmln7NTvE5O3GmQ==} engines: {node: '>=18.0.0'} '@smithy/uuid@1.1.2': @@ -5439,8 +5439,8 @@ packages: resolution: {integrity: sha512-CJDxIgE5I0FH+ttq/Fxy6nRpxP70+e2O048EPe85J2use3XKdatVM7dDVvFNjQudd9B49NPoZ+8PG49zj4Er8Q==} engines: {node: '>= 16'} - '@xmldom/xmldom@0.8.12': - resolution: {integrity: sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg==} + '@xmldom/xmldom@0.8.13': + resolution: {integrity: sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==} engines: {node: '>=10.0.0'} '@xtuc/ieee754@1.2.0': @@ -6168,8 +6168,8 @@ packages: engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} hasBin: true - cross-fetch@4.0.0: - resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + cross-fetch@4.1.0: + resolution: {integrity: sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==} cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} @@ -6916,11 +6916,11 @@ packages: fast-uri@3.0.6: resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} - fast-xml-builder@1.1.4: - resolution: {integrity: sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==} + fast-xml-builder@1.1.5: + resolution: {integrity: sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==} - fast-xml-parser@5.5.8: - resolution: {integrity: sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==} + fast-xml-parser@5.7.1: + resolution: {integrity: sha512-8Cc3f8GUGUULg34pBch/KGyPLglS+OFs05deyOlY7fL2MTagYPKrVQNmR1fLF/yJ9PH5ZSTd3YDF6pnmeZU+zA==} hasBin: true fastify-ip@2.0.0: @@ -7288,8 +7288,8 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} - i18next-http-backend@3.0.2: - resolution: {integrity: sha512-PdlvPnvIp4E1sYi46Ik4tBYh/v/NbYfFFgTjkwFl0is8A18s7/bx9aXqsrOax9WUbeNS6mD2oix7Z0yGGf6m5g==} + i18next-http-backend@3.0.6: + resolution: {integrity: sha512-mBOqy8993jtqAoj6XaI1XeC/8/9v6EPS+681ziegrPvTB0DoaCY7PpTS0SpY56qLMoS4OI1TZEM2Zf59zNh05w==} i18next@25.10.1: resolution: {integrity: sha512-d7MZx1UDamSmjbaqFg00w+EXUTqIB8x8cmYRGsAzQqXFVyrNFprGqPItANtlF6V1tuBFyZyp+4/q2MFqODWerg==} @@ -8803,8 +8803,8 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-expression-matcher@1.2.0: - resolution: {integrity: sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ==} + path-expression-matcher@1.5.0: + resolution: {integrity: sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==} engines: {node: '>=14.0.0'} path-is-absolute@1.0.1: @@ -9036,8 +9036,8 @@ packages: resolution: {integrity: sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg==} engines: {node: '>=12'} - posthog-js@1.370.0: - resolution: {integrity: sha512-0PQCUO6EGbXaOPgXYrcafrXa9B13nDaGc91xCiuwNPK80oovqTmeHfNUNCv1r+xCpEoxw3L1FyBuuLCt5Zz7rg==} + posthog-js@1.372.2: + resolution: {integrity: sha512-FS+vKDXB1vghrVch3EDi3IRcoH5OnLQYxchHWi+8U4D4PzWQZnZLo5vyMRL1+ZUHNEZ2v599uX3UKhRZv2z6Cg==} postmark@4.0.7: resolution: {integrity: sha512-DjNniUl1XNCGUKhCR98ePd5gv16rlUAVKKaU9TUqnE3hDSqfT9XDulu1idjagQmdyGscqnRtXk/puAEiYMeevg==} @@ -9140,8 +9140,8 @@ packages: prosemirror-view@1.40.0: resolution: {integrity: sha512-2G3svX0Cr1sJjkD/DYWSe3cfV5VPVTBOxI9XQEGWJDFEpsZb/gh4MV29ctv+OJx2RFX4BLt09i+6zaGM/ldkCw==} - protobufjs@7.5.4: - resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + protobufjs@7.5.5: + resolution: {integrity: sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==} engines: {node: '>=12.0.0'} proxy-addr@2.0.7: @@ -9846,8 +9846,8 @@ packages: resolution: {integrity: sha512-aT2BU9KkizY9SATf14WhhYVv2uOapBWX0OFWF4xvcj1mPaNotlSc2CsxpS4DS46ZueSppmCF5BX1sNYBtwBvfw==} engines: {node: '>=12.*'} - strnum@2.2.1: - resolution: {integrity: sha512-BwRvNd5/QoAtyW1na1y1LsJGQNvRlkde6Q/ipqqEaivoMdV+B1OMOTVdwR+N/cwVUcIt9PYyHmV8HyexCZSupg==} + strnum@2.2.3: + resolution: {integrity: sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==} strtok3@10.3.4: resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} @@ -10320,8 +10320,8 @@ packages: resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} hasBin: true - uuid@13.0.0: - resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} + uuid@14.0.0: + resolution: {integrity: sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==} hasBin: true v8-compile-cache-lib@3.0.1: @@ -10829,20 +10829,20 @@ snapshots: '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.8 tslib: 2.8.1 '@aws-crypto/crc32c@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.8 tslib: 2.8.1 '@aws-crypto/sha1-browser@5.2.0': dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.8 '@aws-sdk/util-locate-window': 3.535.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -10852,7 +10852,7 @@ snapshots: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.8 '@aws-sdk/util-locate-window': 3.535.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 @@ -10860,7 +10860,7 @@ snapshots: '@aws-crypto/sha256-js@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.8 tslib: 2.8.1 '@aws-crypto/supports-web-crypto@5.2.0': @@ -10869,432 +10869,435 @@ snapshots: '@aws-crypto/util@5.2.0': dependencies: - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.8 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-s3@3.1014.0': + '@aws-sdk/client-s3@3.1037.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.26 - '@aws-sdk/credential-provider-node': 3.972.29 - '@aws-sdk/middleware-bucket-endpoint': 3.972.8 - '@aws-sdk/middleware-expect-continue': 3.972.8 - '@aws-sdk/middleware-flexible-checksums': 3.974.6 - '@aws-sdk/middleware-host-header': 3.972.8 - '@aws-sdk/middleware-location-constraint': 3.972.8 - '@aws-sdk/middleware-logger': 3.972.8 - '@aws-sdk/middleware-recursion-detection': 3.972.9 - '@aws-sdk/middleware-sdk-s3': 3.972.27 - '@aws-sdk/middleware-ssec': 3.972.8 - '@aws-sdk/middleware-user-agent': 3.972.28 - '@aws-sdk/region-config-resolver': 3.972.10 - '@aws-sdk/signature-v4-multi-region': 3.996.15 - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-endpoints': 3.996.5 - '@aws-sdk/util-user-agent-browser': 3.972.8 - '@aws-sdk/util-user-agent-node': 3.973.14 - '@smithy/config-resolver': 4.4.13 - '@smithy/core': 3.23.13 - '@smithy/eventstream-serde-browser': 4.2.12 - '@smithy/eventstream-serde-config-resolver': 4.3.12 - '@smithy/eventstream-serde-node': 4.2.12 - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/hash-blob-browser': 4.2.13 - '@smithy/hash-node': 4.2.12 - '@smithy/hash-stream-node': 4.2.12 - '@smithy/invalid-dependency': 4.2.12 - '@smithy/md5-js': 4.2.12 - '@smithy/middleware-content-length': 4.2.12 - '@smithy/middleware-endpoint': 4.4.28 - '@smithy/middleware-retry': 4.4.46 - '@smithy/middleware-serde': 4.2.16 - '@smithy/middleware-stack': 4.2.12 - '@smithy/node-config-provider': 4.3.12 - '@smithy/node-http-handler': 4.5.1 - '@smithy/protocol-http': 5.3.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/credential-provider-node': 3.972.36 + '@aws-sdk/middleware-bucket-endpoint': 3.972.10 + '@aws-sdk/middleware-expect-continue': 3.972.10 + '@aws-sdk/middleware-flexible-checksums': 3.974.13 + '@aws-sdk/middleware-host-header': 3.972.10 + '@aws-sdk/middleware-location-constraint': 3.972.10 + '@aws-sdk/middleware-logger': 3.972.10 + '@aws-sdk/middleware-recursion-detection': 3.972.11 + '@aws-sdk/middleware-sdk-s3': 3.972.34 + '@aws-sdk/middleware-ssec': 3.972.10 + '@aws-sdk/middleware-user-agent': 3.972.35 + '@aws-sdk/region-config-resolver': 3.972.13 + '@aws-sdk/signature-v4-multi-region': 3.996.22 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.8 + '@aws-sdk/util-user-agent-browser': 3.972.10 + '@aws-sdk/util-user-agent-node': 3.973.21 + '@smithy/config-resolver': 4.4.17 + '@smithy/core': 3.23.17 + '@smithy/eventstream-serde-browser': 4.2.14 + '@smithy/eventstream-serde-config-resolver': 4.3.14 + '@smithy/eventstream-serde-node': 4.2.14 + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/hash-blob-browser': 4.2.15 + '@smithy/hash-node': 4.2.14 + '@smithy/hash-stream-node': 4.2.14 + '@smithy/invalid-dependency': 4.2.14 + '@smithy/md5-js': 4.2.14 + '@smithy/middleware-content-length': 4.2.14 + '@smithy/middleware-endpoint': 4.4.32 + '@smithy/middleware-retry': 4.5.5 + '@smithy/middleware-serde': 4.2.20 + '@smithy/middleware-stack': 4.2.14 + '@smithy/node-config-provider': 4.3.14 + '@smithy/node-http-handler': 4.6.1 + '@smithy/protocol-http': 5.3.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 '@smithy/util-base64': 4.3.2 '@smithy/util-body-length-browser': 4.2.2 '@smithy/util-body-length-node': 4.2.3 - '@smithy/util-defaults-mode-browser': 4.3.44 - '@smithy/util-defaults-mode-node': 4.2.48 - '@smithy/util-endpoints': 3.3.3 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-retry': 4.2.13 - '@smithy/util-stream': 4.5.21 + '@smithy/util-defaults-mode-browser': 4.3.49 + '@smithy/util-defaults-mode-node': 4.2.54 + '@smithy/util-endpoints': 3.4.2 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-retry': 4.3.4 + '@smithy/util-stream': 4.5.25 '@smithy/util-utf8': 4.2.2 - '@smithy/util-waiter': 4.2.14 + '@smithy/util-waiter': 4.2.16 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.973.26': + '@aws-sdk/core@3.974.5': dependencies: - '@aws-sdk/types': 3.973.6 - '@aws-sdk/xml-builder': 3.972.16 - '@smithy/core': 3.23.13 - '@smithy/node-config-provider': 4.3.12 - '@smithy/property-provider': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/signature-v4': 5.3.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/xml-builder': 3.972.19 + '@smithy/core': 3.23.17 + '@smithy/node-config-provider': 4.3.14 + '@smithy/property-provider': 4.2.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/signature-v4': 5.3.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 '@smithy/util-base64': 4.3.2 - '@smithy/util-middleware': 4.2.12 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-retry': 4.3.4 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@aws-sdk/crc64-nvme@3.972.5': + '@aws-sdk/crc64-nvme@3.972.7': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.24': + '@aws-sdk/credential-provider-env@3.972.31': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.26': + '@aws-sdk/credential-provider-http@3.972.33': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/types': 3.973.6 - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/node-http-handler': 4.5.1 - '@smithy/property-provider': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 - '@smithy/util-stream': 4.5.21 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/types': 3.973.8 + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/node-http-handler': 4.6.1 + '@smithy/property-provider': 4.2.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 + '@smithy/util-stream': 4.5.25 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.972.28': + '@aws-sdk/credential-provider-ini@3.972.35': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/credential-provider-env': 3.972.24 - '@aws-sdk/credential-provider-http': 3.972.26 - '@aws-sdk/credential-provider-login': 3.972.28 - '@aws-sdk/credential-provider-process': 3.972.24 - '@aws-sdk/credential-provider-sso': 3.972.28 - '@aws-sdk/credential-provider-web-identity': 3.972.28 - '@aws-sdk/nested-clients': 3.996.18 - '@aws-sdk/types': 3.973.6 - '@smithy/credential-provider-imds': 4.2.12 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/credential-provider-env': 3.972.31 + '@aws-sdk/credential-provider-http': 3.972.33 + '@aws-sdk/credential-provider-login': 3.972.35 + '@aws-sdk/credential-provider-process': 3.972.31 + '@aws-sdk/credential-provider-sso': 3.972.35 + '@aws-sdk/credential-provider-web-identity': 3.972.35 + '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/types': 3.973.8 + '@smithy/credential-provider-imds': 4.2.14 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.972.28': + '@aws-sdk/credential-provider-login@3.972.35': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/nested-clients': 3.996.18 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.972.29': + '@aws-sdk/credential-provider-node@3.972.36': dependencies: - '@aws-sdk/credential-provider-env': 3.972.24 - '@aws-sdk/credential-provider-http': 3.972.26 - '@aws-sdk/credential-provider-ini': 3.972.28 - '@aws-sdk/credential-provider-process': 3.972.24 - '@aws-sdk/credential-provider-sso': 3.972.28 - '@aws-sdk/credential-provider-web-identity': 3.972.28 - '@aws-sdk/types': 3.973.6 - '@smithy/credential-provider-imds': 4.2.12 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/credential-provider-env': 3.972.31 + '@aws-sdk/credential-provider-http': 3.972.33 + '@aws-sdk/credential-provider-ini': 3.972.35 + '@aws-sdk/credential-provider-process': 3.972.31 + '@aws-sdk/credential-provider-sso': 3.972.35 + '@aws-sdk/credential-provider-web-identity': 3.972.35 + '@aws-sdk/types': 3.973.8 + '@smithy/credential-provider-imds': 4.2.14 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.972.24': + '@aws-sdk/credential-provider-process@3.972.31': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.972.28': + '@aws-sdk/credential-provider-sso@3.972.35': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/nested-clients': 3.996.18 - '@aws-sdk/token-providers': 3.1021.0 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/token-providers': 3.1036.0 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.972.28': + '@aws-sdk/credential-provider-web-identity@3.972.35': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/nested-clients': 3.996.18 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/lib-storage@3.1014.0(@aws-sdk/client-s3@3.1014.0)': + '@aws-sdk/lib-storage@3.1037.0(@aws-sdk/client-s3@3.1037.0)': dependencies: - '@aws-sdk/client-s3': 3.1014.0 - '@smithy/abort-controller': 4.2.12 - '@smithy/middleware-endpoint': 4.4.28 - '@smithy/smithy-client': 4.12.8 + '@aws-sdk/client-s3': 3.1037.0 + '@smithy/middleware-endpoint': 4.4.32 + '@smithy/protocol-http': 5.3.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 buffer: 5.6.0 events: 3.3.0 stream-browserify: 3.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-bucket-endpoint@3.972.8': + '@aws-sdk/middleware-bucket-endpoint@3.972.10': dependencies: - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.8 '@aws-sdk/util-arn-parser': 3.972.3 - '@smithy/node-config-provider': 4.3.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 + '@smithy/node-config-provider': 4.3.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 '@smithy/util-config-provider': 4.2.2 tslib: 2.8.1 - '@aws-sdk/middleware-expect-continue@3.972.8': + '@aws-sdk/middleware-expect-continue@3.972.10': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.974.6': + '@aws-sdk/middleware-flexible-checksums@3.974.13': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.973.26 - '@aws-sdk/crc64-nvme': 3.972.5 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/crc64-nvme': 3.972.7 + '@aws-sdk/types': 3.973.8 '@smithy/is-array-buffer': 4.2.2 - '@smithy/node-config-provider': 4.3.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-stream': 4.5.21 + '@smithy/node-config-provider': 4.3.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-stream': 4.5.25 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.972.8': + '@aws-sdk/middleware-host-header@3.972.10': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-location-constraint@3.972.8': + '@aws-sdk/middleware-location-constraint@3.972.10': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-logger@3.972.8': + '@aws-sdk/middleware-logger@3.972.10': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.972.9': + '@aws-sdk/middleware-recursion-detection@3.972.11': dependencies: - '@aws-sdk/types': 3.973.6 + '@aws-sdk/types': 3.973.8 '@aws/lambda-invoke-store': 0.2.3 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.27': + '@aws-sdk/middleware-sdk-s3@3.972.34': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/types': 3.973.6 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/types': 3.973.8 '@aws-sdk/util-arn-parser': 3.972.3 - '@smithy/core': 3.23.13 - '@smithy/node-config-provider': 4.3.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/signature-v4': 5.3.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 + '@smithy/core': 3.23.17 + '@smithy/node-config-provider': 4.3.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/signature-v4': 5.3.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 '@smithy/util-config-provider': 4.2.2 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-stream': 4.5.21 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-stream': 4.5.25 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@aws-sdk/middleware-ssec@3.972.8': + '@aws-sdk/middleware-ssec@3.972.10': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.972.28': + '@aws-sdk/middleware-user-agent@3.972.35': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-endpoints': 3.996.5 - '@smithy/core': 3.23.13 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-retry': 4.2.13 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.8 + '@smithy/core': 3.23.17 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-retry': 4.3.4 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.996.18': + '@aws-sdk/nested-clients@3.997.3': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.973.26 - '@aws-sdk/middleware-host-header': 3.972.8 - '@aws-sdk/middleware-logger': 3.972.8 - '@aws-sdk/middleware-recursion-detection': 3.972.9 - '@aws-sdk/middleware-user-agent': 3.972.28 - '@aws-sdk/region-config-resolver': 3.972.10 - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-endpoints': 3.996.5 - '@aws-sdk/util-user-agent-browser': 3.972.8 - '@aws-sdk/util-user-agent-node': 3.973.14 - '@smithy/config-resolver': 4.4.13 - '@smithy/core': 3.23.13 - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/hash-node': 4.2.12 - '@smithy/invalid-dependency': 4.2.12 - '@smithy/middleware-content-length': 4.2.12 - '@smithy/middleware-endpoint': 4.4.28 - '@smithy/middleware-retry': 4.4.46 - '@smithy/middleware-serde': 4.2.16 - '@smithy/middleware-stack': 4.2.12 - '@smithy/node-config-provider': 4.3.12 - '@smithy/node-http-handler': 4.5.1 - '@smithy/protocol-http': 5.3.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/middleware-host-header': 3.972.10 + '@aws-sdk/middleware-logger': 3.972.10 + '@aws-sdk/middleware-recursion-detection': 3.972.11 + '@aws-sdk/middleware-user-agent': 3.972.35 + '@aws-sdk/region-config-resolver': 3.972.13 + '@aws-sdk/signature-v4-multi-region': 3.996.22 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-endpoints': 3.996.8 + '@aws-sdk/util-user-agent-browser': 3.972.10 + '@aws-sdk/util-user-agent-node': 3.973.21 + '@smithy/config-resolver': 4.4.17 + '@smithy/core': 3.23.17 + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/hash-node': 4.2.14 + '@smithy/invalid-dependency': 4.2.14 + '@smithy/middleware-content-length': 4.2.14 + '@smithy/middleware-endpoint': 4.4.32 + '@smithy/middleware-retry': 4.5.5 + '@smithy/middleware-serde': 4.2.20 + '@smithy/middleware-stack': 4.2.14 + '@smithy/node-config-provider': 4.3.14 + '@smithy/node-http-handler': 4.6.1 + '@smithy/protocol-http': 5.3.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 '@smithy/util-base64': 4.3.2 '@smithy/util-body-length-browser': 4.2.2 '@smithy/util-body-length-node': 4.2.3 - '@smithy/util-defaults-mode-browser': 4.3.44 - '@smithy/util-defaults-mode-node': 4.2.48 - '@smithy/util-endpoints': 3.3.3 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-retry': 4.2.13 + '@smithy/util-defaults-mode-browser': 4.3.49 + '@smithy/util-defaults-mode-node': 4.2.54 + '@smithy/util-endpoints': 3.4.2 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-retry': 4.3.4 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/region-config-resolver@3.972.10': + '@aws-sdk/region-config-resolver@3.972.13': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/config-resolver': 4.4.13 - '@smithy/node-config-provider': 4.3.12 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@smithy/config-resolver': 4.4.17 + '@smithy/node-config-provider': 4.3.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/s3-request-presigner@3.1014.0': + '@aws-sdk/s3-request-presigner@3.1037.0': dependencies: - '@aws-sdk/signature-v4-multi-region': 3.996.15 - '@aws-sdk/types': 3.973.6 - '@aws-sdk/util-format-url': 3.972.8 - '@smithy/middleware-endpoint': 4.4.28 - '@smithy/protocol-http': 5.3.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 + '@aws-sdk/signature-v4-multi-region': 3.996.22 + '@aws-sdk/types': 3.973.8 + '@aws-sdk/util-format-url': 3.972.10 + '@smithy/middleware-endpoint': 4.4.32 + '@smithy/protocol-http': 5.3.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.996.15': + '@aws-sdk/signature-v4-multi-region@3.996.22': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.972.27 - '@aws-sdk/types': 3.973.6 - '@smithy/protocol-http': 5.3.12 - '@smithy/signature-v4': 5.3.12 - '@smithy/types': 4.13.1 + '@aws-sdk/middleware-sdk-s3': 3.972.34 + '@aws-sdk/types': 3.973.8 + '@smithy/protocol-http': 5.3.14 + '@smithy/signature-v4': 5.3.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1021.0': + '@aws-sdk/token-providers@3.1036.0': dependencies: - '@aws-sdk/core': 3.973.26 - '@aws-sdk/nested-clients': 3.996.18 - '@aws-sdk/types': 3.973.6 - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@aws-sdk/core': 3.974.5 + '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/types': 3.973.8 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/types@3.973.6': + '@aws-sdk/types@3.973.8': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 '@aws-sdk/util-arn-parser@3.972.3': dependencies: tslib: 2.8.1 - '@aws-sdk/util-endpoints@3.996.5': + '@aws-sdk/util-endpoints@3.996.8': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - '@smithy/util-endpoints': 3.3.3 + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 + '@smithy/util-endpoints': 3.4.2 tslib: 2.8.1 - '@aws-sdk/util-format-url@3.972.8': + '@aws-sdk/util-format-url@3.972.10': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/querystring-builder': 4.2.12 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@smithy/querystring-builder': 4.2.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 '@aws-sdk/util-locate-window@3.535.0': dependencies: tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.972.8': + '@aws-sdk/util-user-agent-browser@3.972.10': dependencies: - '@aws-sdk/types': 3.973.6 - '@smithy/types': 4.13.1 + '@aws-sdk/types': 3.973.8 + '@smithy/types': 4.14.1 bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.973.14': + '@aws-sdk/util-user-agent-node@3.973.21': dependencies: - '@aws-sdk/middleware-user-agent': 3.972.28 - '@aws-sdk/types': 3.973.6 - '@smithy/node-config-provider': 4.3.12 - '@smithy/types': 4.13.1 + '@aws-sdk/middleware-user-agent': 3.972.35 + '@aws-sdk/types': 3.973.8 + '@smithy/node-config-provider': 4.3.14 + '@smithy/types': 4.14.1 '@smithy/util-config-provider': 4.2.2 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.16': + '@aws-sdk/xml-builder@3.972.19': dependencies: - '@smithy/types': 4.13.1 - fast-xml-parser: 5.5.8 + '@smithy/types': 4.14.1 + fast-xml-parser: 5.7.1 tslib: 2.8.1 '@aws/lambda-invoke-store@0.2.3': {} @@ -13455,6 +13458,8 @@ snapshots: '@noble/hashes@2.0.1': {} + '@nodable/entities@2.1.0': {} + '@node-saml/node-saml@5.1.0': dependencies: '@types/debug': 4.1.12 @@ -13462,7 +13467,7 @@ snapshots: '@types/xml-encryption': 1.2.4 '@types/xml2js': 0.4.14 '@xmldom/is-dom-node': 1.0.1 - '@xmldom/xmldom': 0.8.12 + '@xmldom/xmldom': 0.8.13 debug: 4.4.0 xml-crypto: 6.1.2 xml-encryption: 3.1.0 @@ -13620,7 +13625,7 @@ snapshots: '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) - protobufjs: 7.5.4 + protobufjs: 7.5.5 '@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0)': dependencies: @@ -13666,9 +13671,11 @@ snapshots: '@pkgr/core@0.2.9': {} - '@posthog/core@1.26.0': {} + '@posthog/core@1.27.6': + dependencies: + '@posthog/types': 1.372.2 - '@posthog/types@1.370.0': {} + '@posthog/types@1.372.2': {} '@protobufjs/aspromise@1.1.2': {} @@ -14649,11 +14656,6 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@smithy/abort-controller@4.2.12': - dependencies: - '@smithy/types': 4.13.1 - tslib: 2.8.1 - '@smithy/chunked-blob-reader-native@4.2.3': dependencies: '@smithy/util-base64': 4.3.2 @@ -14663,97 +14665,97 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/config-resolver@4.4.13': + '@smithy/config-resolver@4.4.17': dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/types': 4.13.1 + '@smithy/node-config-provider': 4.3.14 + '@smithy/types': 4.14.1 '@smithy/util-config-provider': 4.2.2 - '@smithy/util-endpoints': 3.3.3 - '@smithy/util-middleware': 4.2.12 + '@smithy/util-endpoints': 3.4.2 + '@smithy/util-middleware': 4.2.14 tslib: 2.8.1 - '@smithy/core@3.23.13': + '@smithy/core@3.23.17': dependencies: - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 '@smithy/util-base64': 4.3.2 '@smithy/util-body-length-browser': 4.2.2 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-stream': 4.5.21 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-stream': 4.5.25 '@smithy/util-utf8': 4.2.2 '@smithy/uuid': 1.1.2 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.2.12': + '@smithy/credential-provider-imds@4.2.14': dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/property-provider': 4.2.12 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 + '@smithy/node-config-provider': 4.3.14 + '@smithy/property-provider': 4.2.14 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 tslib: 2.8.1 - '@smithy/eventstream-codec@4.2.12': + '@smithy/eventstream-codec@4.2.14': dependencies: '@aws-crypto/crc32': 5.2.0 - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 '@smithy/util-hex-encoding': 4.2.2 tslib: 2.8.1 - '@smithy/eventstream-serde-browser@4.2.12': + '@smithy/eventstream-serde-browser@4.2.14': dependencies: - '@smithy/eventstream-serde-universal': 4.2.12 - '@smithy/types': 4.13.1 + '@smithy/eventstream-serde-universal': 4.2.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/eventstream-serde-config-resolver@4.3.12': + '@smithy/eventstream-serde-config-resolver@4.3.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/eventstream-serde-node@4.2.12': + '@smithy/eventstream-serde-node@4.2.14': dependencies: - '@smithy/eventstream-serde-universal': 4.2.12 - '@smithy/types': 4.13.1 + '@smithy/eventstream-serde-universal': 4.2.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/eventstream-serde-universal@4.2.12': + '@smithy/eventstream-serde-universal@4.2.14': dependencies: - '@smithy/eventstream-codec': 4.2.12 - '@smithy/types': 4.13.1 + '@smithy/eventstream-codec': 4.2.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.3.15': + '@smithy/fetch-http-handler@5.3.17': dependencies: - '@smithy/protocol-http': 5.3.12 - '@smithy/querystring-builder': 4.2.12 - '@smithy/types': 4.13.1 + '@smithy/protocol-http': 5.3.14 + '@smithy/querystring-builder': 4.2.14 + '@smithy/types': 4.14.1 '@smithy/util-base64': 4.3.2 tslib: 2.8.1 - '@smithy/hash-blob-browser@4.2.13': + '@smithy/hash-blob-browser@4.2.15': dependencies: '@smithy/chunked-blob-reader': 5.2.2 '@smithy/chunked-blob-reader-native': 4.2.3 - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/hash-node@4.2.12': + '@smithy/hash-node@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 '@smithy/util-buffer-from': 4.2.2 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/hash-stream-node@4.2.12': + '@smithy/hash-stream-node@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/invalid-dependency@4.2.12': + '@smithy/invalid-dependency@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': @@ -14764,126 +14766,127 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/md5-js@4.2.12': + '@smithy/md5-js@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/middleware-content-length@4.2.12': + '@smithy/middleware-content-length@4.2.14': dependencies: - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/middleware-endpoint@4.4.28': + '@smithy/middleware-endpoint@4.4.32': dependencies: - '@smithy/core': 3.23.13 - '@smithy/middleware-serde': 4.2.16 - '@smithy/node-config-provider': 4.3.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 - '@smithy/url-parser': 4.2.12 - '@smithy/util-middleware': 4.2.12 + '@smithy/core': 3.23.17 + '@smithy/middleware-serde': 4.2.20 + '@smithy/node-config-provider': 4.3.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 + '@smithy/url-parser': 4.2.14 + '@smithy/util-middleware': 4.2.14 tslib: 2.8.1 - '@smithy/middleware-retry@4.4.46': + '@smithy/middleware-retry@4.5.5': dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/service-error-classification': 4.2.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 - '@smithy/util-middleware': 4.2.12 - '@smithy/util-retry': 4.2.13 + '@smithy/core': 3.23.17 + '@smithy/node-config-provider': 4.3.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/service-error-classification': 4.3.0 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 + '@smithy/util-middleware': 4.2.14 + '@smithy/util-retry': 4.3.4 '@smithy/uuid': 1.1.2 tslib: 2.8.1 - '@smithy/middleware-serde@4.2.16': + '@smithy/middleware-serde@4.2.20': dependencies: - '@smithy/core': 3.23.13 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 + '@smithy/core': 3.23.17 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/middleware-stack@4.2.12': + '@smithy/middleware-stack@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/node-config-provider@4.3.12': + '@smithy/node-config-provider@4.3.14': dependencies: - '@smithy/property-provider': 4.2.12 - '@smithy/shared-ini-file-loader': 4.4.7 - '@smithy/types': 4.13.1 + '@smithy/property-provider': 4.2.14 + '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/node-http-handler@4.5.1': + '@smithy/node-http-handler@4.6.1': dependencies: - '@smithy/protocol-http': 5.3.12 - '@smithy/querystring-builder': 4.2.12 - '@smithy/types': 4.13.1 + '@smithy/protocol-http': 5.3.14 + '@smithy/querystring-builder': 4.2.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/property-provider@4.2.12': + '@smithy/property-provider@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/protocol-http@5.3.12': + '@smithy/protocol-http@5.3.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/querystring-builder@4.2.12': + '@smithy/querystring-builder@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 '@smithy/util-uri-escape': 4.2.2 tslib: 2.8.1 - '@smithy/querystring-parser@4.2.12': + '@smithy/querystring-parser@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/service-error-classification@4.2.12': + '@smithy/service-error-classification@4.3.0': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 - '@smithy/shared-ini-file-loader@4.4.7': + '@smithy/shared-ini-file-loader@4.4.9': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/signature-v4@5.3.12': + '@smithy/signature-v4@5.3.14': dependencies: '@smithy/is-array-buffer': 4.2.2 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 '@smithy/util-hex-encoding': 4.2.2 - '@smithy/util-middleware': 4.2.12 + '@smithy/util-middleware': 4.2.14 '@smithy/util-uri-escape': 4.2.2 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@smithy/smithy-client@4.12.8': + '@smithy/smithy-client@4.12.13': dependencies: - '@smithy/core': 3.23.13 - '@smithy/middleware-endpoint': 4.4.28 - '@smithy/middleware-stack': 4.2.12 - '@smithy/protocol-http': 5.3.12 - '@smithy/types': 4.13.1 - '@smithy/util-stream': 4.5.21 + '@smithy/core': 3.23.17 + '@smithy/middleware-endpoint': 4.4.32 + '@smithy/middleware-stack': 4.2.14 + '@smithy/protocol-http': 5.3.14 + '@smithy/types': 4.14.1 + '@smithy/util-stream': 4.5.25 tslib: 2.8.1 - '@smithy/types@4.13.1': + '@smithy/types@4.14.1': dependencies: tslib: 2.8.1 - '@smithy/url-parser@4.2.12': + '@smithy/url-parser@4.2.14': dependencies: - '@smithy/querystring-parser': 4.2.12 - '@smithy/types': 4.13.1 + '@smithy/querystring-parser': 4.2.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 '@smithy/util-base64@4.3.2': @@ -14914,49 +14917,49 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@4.3.44': + '@smithy/util-defaults-mode-browser@4.3.49': dependencies: - '@smithy/property-provider': 4.2.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 + '@smithy/property-provider': 4.2.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@4.2.48': + '@smithy/util-defaults-mode-node@4.2.54': dependencies: - '@smithy/config-resolver': 4.4.13 - '@smithy/credential-provider-imds': 4.2.12 - '@smithy/node-config-provider': 4.3.12 - '@smithy/property-provider': 4.2.12 - '@smithy/smithy-client': 4.12.8 - '@smithy/types': 4.13.1 + '@smithy/config-resolver': 4.4.17 + '@smithy/credential-provider-imds': 4.2.14 + '@smithy/node-config-provider': 4.3.14 + '@smithy/property-provider': 4.2.14 + '@smithy/smithy-client': 4.12.13 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/util-endpoints@3.3.3': + '@smithy/util-endpoints@3.4.2': dependencies: - '@smithy/node-config-provider': 4.3.12 - '@smithy/types': 4.13.1 + '@smithy/node-config-provider': 4.3.14 + '@smithy/types': 4.14.1 tslib: 2.8.1 '@smithy/util-hex-encoding@4.2.2': dependencies: tslib: 2.8.1 - '@smithy/util-middleware@4.2.12': + '@smithy/util-middleware@4.2.14': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/util-retry@4.2.13': + '@smithy/util-retry@4.3.4': dependencies: - '@smithy/service-error-classification': 4.2.12 - '@smithy/types': 4.13.1 + '@smithy/service-error-classification': 4.3.0 + '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/util-stream@4.5.21': + '@smithy/util-stream@4.5.25': dependencies: - '@smithy/fetch-http-handler': 5.3.15 - '@smithy/node-http-handler': 4.5.1 - '@smithy/types': 4.13.1 + '@smithy/fetch-http-handler': 5.3.17 + '@smithy/node-http-handler': 4.6.1 + '@smithy/types': 4.14.1 '@smithy/util-base64': 4.3.2 '@smithy/util-buffer-from': 4.2.2 '@smithy/util-hex-encoding': 4.2.2 @@ -14977,9 +14980,9 @@ snapshots: '@smithy/util-buffer-from': 4.2.2 tslib: 2.8.1 - '@smithy/util-waiter@4.2.14': + '@smithy/util-waiter@4.2.16': dependencies: - '@smithy/types': 4.13.1 + '@smithy/types': 4.14.1 tslib: 2.8.1 '@smithy/uuid@1.1.2': @@ -16039,7 +16042,7 @@ snapshots: '@xmldom/is-dom-node@1.0.1': {} - '@xmldom/xmldom@0.8.12': {} + '@xmldom/xmldom@0.8.13': {} '@xtuc/ieee754@1.2.0': {} @@ -16853,7 +16856,7 @@ snapshots: dependencies: cross-spawn: 7.0.6 - cross-fetch@4.0.0: + cross-fetch@4.1.0: dependencies: node-fetch: 2.7.0 transitivePeerDependencies: @@ -17833,15 +17836,16 @@ snapshots: fast-uri@3.0.6: {} - fast-xml-builder@1.1.4: + fast-xml-builder@1.1.5: dependencies: - path-expression-matcher: 1.2.0 + path-expression-matcher: 1.5.0 - fast-xml-parser@5.5.8: + fast-xml-parser@5.7.1: dependencies: - fast-xml-builder: 1.1.4 - path-expression-matcher: 1.2.0 - strnum: 2.2.1 + '@nodable/entities': 2.1.0 + fast-xml-builder: 1.1.5 + path-expression-matcher: 1.5.0 + strnum: 2.2.3 fastify-ip@2.0.0: dependencies: @@ -18250,9 +18254,9 @@ snapshots: human-signals@2.1.0: {} - i18next-http-backend@3.0.2: + i18next-http-backend@3.0.6: dependencies: - cross-fetch: 4.0.0 + cross-fetch: 4.1.0 transitivePeerDependencies: - encoding @@ -19386,7 +19390,7 @@ snapshots: mammoth@1.12.0: dependencies: - '@xmldom/xmldom': 0.8.12 + '@xmldom/xmldom': 0.8.13 argparse: 1.0.10 base64-js: 1.5.1 bluebird: 3.4.7 @@ -19942,7 +19946,7 @@ snapshots: path-exists@4.0.0: {} - path-expression-matcher@1.2.0: {} + path-expression-matcher@1.5.0: {} path-is-absolute@1.0.1: {} @@ -20187,15 +20191,15 @@ snapshots: postgres@3.4.8: {} - posthog-js@1.370.0: + posthog-js@1.372.2: dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.208.0 '@opentelemetry/exporter-logs-otlp-http': 0.208.0(@opentelemetry/api@1.9.0) '@opentelemetry/resources': 2.5.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0) - '@posthog/core': 1.26.0 - '@posthog/types': 1.370.0 + '@posthog/core': 1.27.6 + '@posthog/types': 1.372.2 core-js: 3.43.0 dompurify: 3.4.1 fflate: 0.4.8 @@ -20349,7 +20353,7 @@ snapshots: prosemirror-state: 1.4.3 prosemirror-transform: 1.10.4 - protobufjs@7.5.4: + protobufjs@7.5.5: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 @@ -21249,7 +21253,7 @@ snapshots: '@types/node': 25.5.0 qs: 6.14.2 - strnum@2.2.1: {} + strnum@2.2.3: {} strtok3@10.3.4: dependencies: @@ -21734,7 +21738,7 @@ snapshots: uuid@11.1.0: {} - uuid@13.0.0: {} + uuid@14.0.0: {} v8-compile-cache-lib@3.0.1: {} @@ -21981,12 +21985,12 @@ snapshots: xml-crypto@6.1.2: dependencies: '@xmldom/is-dom-node': 1.0.1 - '@xmldom/xmldom': 0.8.12 + '@xmldom/xmldom': 0.8.13 xpath: 0.0.33 xml-encryption@3.1.0: dependencies: - '@xmldom/xmldom': 0.8.12 + '@xmldom/xmldom': 0.8.13 escape-html: 1.0.3 xpath: 0.0.32 From 15b8908b1ae829c197211beb5605e8983c80db0f Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:23:47 +0100 Subject: [PATCH 04/63] update postcss --- apps/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/package.json b/apps/client/package.json index b54b86091..2ddafdcf6 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -74,7 +74,7 @@ "eslint-plugin-react-refresh": "^0.5.2", "globals": "^15.13.0", "optics-ts": "^2.4.1", - "postcss": "^8.5.8", + "postcss": "^8.5.12", "postcss-preset-mantine": "^1.18.0", "postcss-simple-vars": "^7.0.1", "prettier": "^3.8.1", From fad410ef2343b9c7e9368be977fe5eb9eda532e5 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:50:42 +0100 Subject: [PATCH 05/63] chore: add undici for oidc proxy support (#2132) --- apps/server/package.json | 1 + pnpm-lock.yaml | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/apps/server/package.json b/apps/server/package.json index 10a13b61d..f9c290ac8 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -117,6 +117,7 @@ "tmp-promise": "^3.0.3", "tseep": "^1.3.1", "typesense": "^3.0.5", + "undici": "7.24.0", "ws": "^8.20.0", "yauzl": "^3.2.1", "zod": "^4.3.6" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73f773844..3977df72e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -719,6 +719,9 @@ importers: typesense: specifier: ^3.0.5 version: 3.0.5(@babel/runtime@7.29.2) + undici: + specifier: 7.24.0 + version: 7.24.0 ws: specifier: 8.20.0 version: 8.20.0 @@ -4005,6 +4008,7 @@ packages: '@react-email/components@1.0.10': resolution: {integrity: sha512-r/BnqfAjr3apcvn/NDx2DqNRD5BP5wZLRdjn2IVHXjt4KmQ5RHWSCAvFiXAzRHys1BWQ2zgIc7cpWePUcAl+nw==} engines: {node: '>=20.0.0'} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. peerDependencies: react: ^18.0 || ^19.0 || ^19.0.0-rc From fe44dc92a92806ab6468f8448fc35caa529617b5 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 27 Apr 2026 15:51:23 +0100 Subject: [PATCH 06/63] sync --- apps/server/src/ee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/ee b/apps/server/src/ee index 36d6b68b9..4101fc427 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit 36d6b68b9307685c362ba9eaf6d1b8e39fee0762 +Subproject commit 4101fc427b785e2711c0f608c377d641a2e4be78 From 980521f95792ddd382ebbc275467a8319a351bae Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 27 Apr 2026 16:06:32 +0100 Subject: [PATCH 07/63] v0.80.1 --- apps/client/package.json | 2 +- apps/server/package.json | 2 +- package.json | 2 +- pnpm-lock.yaml | 62 ++++++++++++++++++++-------------------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/apps/client/package.json b/apps/client/package.json index 2ddafdcf6..404df47ee 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -1,7 +1,7 @@ { "name": "client", "private": true, - "version": "0.80.0", + "version": "0.80.1", "scripts": { "dev": "vite", "build": "tsc && vite build", diff --git a/apps/server/package.json b/apps/server/package.json index f9c290ac8..7c97763b7 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -1,6 +1,6 @@ { "name": "server", - "version": "0.80.0", + "version": "0.80.1", "description": "", "author": "", "private": true, diff --git a/package.json b/package.json index 3e4b7373c..589721623 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "docmost", "homepage": "https://docmost.com", - "version": "0.80.0", + "version": "0.80.1", "private": true, "scripts": { "build": "nx run-many -t build", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3977df72e..4ceb29771 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -415,7 +415,7 @@ importers: version: 18.3.1 '@vitejs/plugin-react': specifier: ^6.0.1 - version: 6.0.1(vite@8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.8))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)) + version: 6.0.1(vite@8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)) eslint: specifier: ^9.28.0 version: 9.39.4(jiti@2.4.2) @@ -435,14 +435,14 @@ importers: specifier: ^2.4.1 version: 2.4.1 postcss: - specifier: ^8.5.8 - version: 8.5.8 + specifier: ^8.5.12 + version: 8.5.12 postcss-preset-mantine: specifier: ^1.18.0 - version: 1.18.0(postcss@8.5.8) + version: 1.18.0(postcss@8.5.12) postcss-simple-vars: specifier: ^7.0.1 - version: 7.0.1(postcss@8.5.8) + version: 7.0.1(postcss@8.5.12) prettier: specifier: ^3.8.1 version: 3.8.1 @@ -454,7 +454,7 @@ importers: version: 8.57.1(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3) vite: specifier: 8.0.5 - version: 8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.8))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) apps/server: dependencies: @@ -9016,8 +9016,8 @@ packages: peerDependencies: postcss: ^8.2.1 - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + postcss@8.5.12: + resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} engines: {node: ^10 || ^12 || >=14} postgres-array@2.0.0: @@ -15963,10 +15963,10 @@ snapshots: '@vercel/oidc@3.1.0': {} - '@vitejs/plugin-react@6.0.1(vite@8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.8))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3))': + '@vitejs/plugin-react@6.0.1(vite@8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 - vite: 8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.8))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) '@webassemblyjs/ast@1.14.1': dependencies: @@ -20140,40 +20140,40 @@ snapshots: possible-typed-array-names@1.0.0: {} - postcss-js@4.0.1(postcss@8.5.8): + postcss-js@4.0.1(postcss@8.5.12): dependencies: camelcase-css: 2.0.1 - postcss: 8.5.8 + postcss: 8.5.12 - postcss-mixins@12.1.2(postcss@8.5.8): + postcss-mixins@12.1.2(postcss@8.5.12): dependencies: - postcss: 8.5.8 - postcss-js: 4.0.1(postcss@8.5.8) - postcss-simple-vars: 7.0.1(postcss@8.5.8) - sugarss: 5.0.1(postcss@8.5.8) + postcss: 8.5.12 + postcss-js: 4.0.1(postcss@8.5.12) + postcss-simple-vars: 7.0.1(postcss@8.5.12) + sugarss: 5.0.1(postcss@8.5.12) tinyglobby: 0.2.15 - postcss-nested@7.0.2(postcss@8.5.8): + postcss-nested@7.0.2(postcss@8.5.12): dependencies: - postcss: 8.5.8 + postcss: 8.5.12 postcss-selector-parser: 7.1.1 - postcss-preset-mantine@1.18.0(postcss@8.5.8): + postcss-preset-mantine@1.18.0(postcss@8.5.12): dependencies: - postcss: 8.5.8 - postcss-mixins: 12.1.2(postcss@8.5.8) - postcss-nested: 7.0.2(postcss@8.5.8) + postcss: 8.5.12 + postcss-mixins: 12.1.2(postcss@8.5.12) + postcss-nested: 7.0.2(postcss@8.5.12) postcss-selector-parser@7.1.1: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-simple-vars@7.0.1(postcss@8.5.8): + postcss-simple-vars@7.0.1(postcss@8.5.12): dependencies: - postcss: 8.5.8 + postcss: 8.5.12 - postcss@8.5.8: + postcss@8.5.12: dependencies: nanoid: 3.3.8 picocolors: 1.1.1 @@ -21271,9 +21271,9 @@ snapshots: stylis@4.3.6: {} - sugarss@5.0.1(postcss@8.5.8): + sugarss@5.0.1(postcss@8.5.12): dependencies: - postcss: 8.5.8 + postcss: 8.5.12 superagent@10.3.0: dependencies: @@ -21756,11 +21756,11 @@ snapshots: vary@1.1.2: {} - vite@8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.8))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3): + vite@8.0.5(@types/node@22.19.1)(esbuild@0.27.4)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.8 + postcss: 8.5.12 rolldown: 1.0.0-rc.12 tinyglobby: 0.2.15 optionalDependencies: @@ -21769,7 +21769,7 @@ snapshots: fsevents: 2.3.3 jiti: 2.4.2 less: 4.2.0 - sugarss: 5.0.1(postcss@8.5.8) + sugarss: 5.0.1(postcss@8.5.12) terser: 5.39.0 tsx: 4.21.0 yaml: 2.8.3 From 3ecf27c6b0191e7adb5789e02c2995f446291052 Mon Sep 17 00:00:00 2001 From: Olivier Lambert Date: Wed, 29 Apr 2026 10:36:38 +0200 Subject: [PATCH 08/63] fix(page-permission): make people-with-access list scroll past 4 entries (#2137) The "People with access" list in the page share modal used , which caps the container height but does not make the inner viewport scroll (no fixed height is given to the viewport). Items beyond ~4 entries were rendered correctly but clipped out of view. Switches to , which is Mantine's dedicated primitive for "grow with content up to a max, then scroll". Closes #2135 --- .../ee/page-permission/components/page-permission-list.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/client/src/ee/page-permission/components/page-permission-list.tsx b/apps/client/src/ee/page-permission/components/page-permission-list.tsx index e586b9683..111bb83ff 100644 --- a/apps/client/src/ee/page-permission/components/page-permission-list.tsx +++ b/apps/client/src/ee/page-permission/components/page-permission-list.tsx @@ -140,7 +140,7 @@ export function PagePermissionList({ )} - + {sortedMembers.map((member) => ( )} - + ); } From 24be90b95f49590cbab011b707106c2dc8573ee0 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Wed, 29 Apr 2026 10:01:47 +0100 Subject: [PATCH 09/63] fix: duplicate PDF uploads (#2139) --- .../editor/components/attachment/upload-attachment-action.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/client/src/features/editor/components/attachment/upload-attachment-action.tsx b/apps/client/src/features/editor/components/attachment/upload-attachment-action.tsx index 9f668963f..e9408891b 100644 --- a/apps/client/src/features/editor/components/attachment/upload-attachment-action.tsx +++ b/apps/client/src/features/editor/components/attachment/upload-attachment-action.tsx @@ -19,7 +19,9 @@ export const uploadAttachmentAction = handleAttachmentUpload({ }, validateFn: (file, allowMedia: boolean) => { if ( - (file.type.includes("image/") || file.type.includes("video/")) && + (file.type.includes("image/") || + file.type.includes("video/") || + file.type === "application/pdf") && !allowMedia ) { return false; From b16f1e5a55cd39571bcd5a323bc7aaf8fa2ca5a1 Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Thu, 30 Apr 2026 19:36:40 -0400 Subject: [PATCH 10/63] fix: ctrl-k behavior on macOS (#2052) * Improve cmd-k / ctrl-k behavior Use cmd-k on macOS/iOS for search and keep ctrl-k everywhere else. Fixes a bug where ctrl-k on macOS, which cuts to the end of the line, was also triggering the search prompt. * comment submit: cmd-enter (mac) / ctrl-enter (win/linux) --- .../src/features/comment/components/comment-editor.tsx | 3 ++- apps/client/src/features/editor/page-editor.tsx | 6 +++--- apps/client/src/features/editor/title-editor.tsx | 5 +++-- .../src/features/search/components/search-control.tsx | 3 ++- apps/client/src/lib/utils.tsx | 9 +++++++++ 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/client/src/features/comment/components/comment-editor.tsx b/apps/client/src/features/comment/components/comment-editor.tsx index 067391f48..0fdc7395e 100644 --- a/apps/client/src/features/comment/components/comment-editor.tsx +++ b/apps/client/src/features/comment/components/comment-editor.tsx @@ -10,6 +10,7 @@ import { useTranslation } from "react-i18next"; import EmojiCommand from "@/features/editor/extensions/emoji-command"; import mentionRenderItems from "@/features/editor/components/mention/mention-suggestion"; import MentionView from "@/features/editor/components/mention/mention-view"; +import { platformModifierKey } from "@/lib"; interface CommentEditorProps { defaultContent?: any; @@ -83,7 +84,7 @@ const CommentEditor = forwardRef( } } - if ((event.ctrlKey || event.metaKey) && event.key === "Enter") { + if (platformModifierKey(event) && event.code === "Enter") { event.preventDefault(); if (onSave) onSave(); diff --git a/apps/client/src/features/editor/page-editor.tsx b/apps/client/src/features/editor/page-editor.tsx index 7cc4723ac..30ccc2e48 100644 --- a/apps/client/src/features/editor/page-editor.tsx +++ b/apps/client/src/features/editor/page-editor.tsx @@ -62,7 +62,7 @@ import { useIdle } from "@/hooks/use-idle.ts"; import { queryClient } from "@/main.tsx"; import { IPage } from "@/features/page/types/page.types.ts"; import { useParams } from "react-router-dom"; -import { extractPageSlugId } from "@/lib"; +import { extractPageSlugId, platformModifierKey } from "@/lib"; import { FIVE_MINUTES } from "@/lib/constants.ts"; import { PageEditMode } from "@/features/user/types/user.types.ts"; import { jwtDecode } from "jwt-decode"; @@ -232,11 +232,11 @@ export default function PageEditor({ scrollMargin: 80, handleDOMEvents: { keydown: (_view, event) => { - if ((event.ctrlKey || event.metaKey) && event.code === "KeyS") { + if (platformModifierKey(event) && event.code === "KeyS") { event.preventDefault(); return true; } - if ((event.ctrlKey || event.metaKey) && event.code === "KeyK") { + if (platformModifierKey(event) && event.code === "KeyK") { searchSpotlight.open(); return true; } diff --git a/apps/client/src/features/editor/title-editor.tsx b/apps/client/src/features/editor/title-editor.tsx index 15c3ff028..e61d8c042 100644 --- a/apps/client/src/features/editor/title-editor.tsx +++ b/apps/client/src/features/editor/title-editor.tsx @@ -27,6 +27,7 @@ import localEmitter from "@/lib/local-emitter.ts"; import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts"; import { PageEditMode } from "@/features/user/types/user.types.ts"; import { searchSpotlight } from "@/features/search/constants.ts"; +import { platformModifierKey } from "@/lib"; export interface TitleEditorProps { pageId: string; @@ -90,11 +91,11 @@ export function TitleEditor({ editorProps: { handleDOMEvents: { keydown: (_view, event) => { - if ((event.ctrlKey || event.metaKey) && event.code === "KeyS") { + if (platformModifierKey(event) && event.code === "KeyS") { event.preventDefault(); return true; } - if ((event.ctrlKey || event.metaKey) && event.code === "KeyK") { + if (platformModifierKey(event) && event.code === "KeyK") { searchSpotlight.open(); return true; } diff --git a/apps/client/src/features/search/components/search-control.tsx b/apps/client/src/features/search/components/search-control.tsx index a98909b7b..3a689e284 100644 --- a/apps/client/src/features/search/components/search-control.tsx +++ b/apps/client/src/features/search/components/search-control.tsx @@ -13,6 +13,7 @@ import { import classes from "./search-control.module.css"; import React from "react"; import { useTranslation } from "react-i18next"; +import { platformModifierLabel } from "@/lib"; interface SearchControlProps extends BoxProps, ElementProps<"button"> {} @@ -27,7 +28,7 @@ export function SearchControl({ className, ...others }: SearchControlProps) { {t("Search")} - Ctrl + K + {platformModifierLabel} + K diff --git a/apps/client/src/lib/utils.tsx b/apps/client/src/lib/utils.tsx index 5f640d456..fe97f7189 100644 --- a/apps/client/src/lib/utils.tsx +++ b/apps/client/src/lib/utils.tsx @@ -100,6 +100,15 @@ export const normalizeUrl = (url: string): string => { return `https://${url}`; }; +const _isApple = /mac|iphone|ipad|ipod/i.test(navigator.platform ?? ""); + +/// Cmd key on Apple devices, Ctrl key everywhere else +export function platformModifierKey(event: KeyboardEvent): boolean { + return _isApple ? event.metaKey : event.ctrlKey; +} + +export const platformModifierLabel = _isApple ? "⌘" : "Ctrl"; + export function castToBoolean(value: unknown): boolean { if (value == null) { return false; From 9943e104a55196326a6d26fcccd7f24e0adde3fc Mon Sep 17 00:00:00 2001 From: Sarthak Chaturvedi <84394327+mayhemking007@users.noreply.github.com> Date: Fri, 1 May 2026 05:07:59 +0530 Subject: [PATCH 11/63] fix(i18n): Correct German column count label rendering (#2131) --- apps/client/public/locales/de-DE/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/client/public/locales/de-DE/translation.json b/apps/client/public/locales/de-DE/translation.json index b6caf4d61..5c9e2d44c 100644 --- a/apps/client/public/locales/de-DE/translation.json +++ b/apps/client/public/locales/de-DE/translation.json @@ -391,7 +391,7 @@ "Write anything. Enter \"/\" for commands": "Schreiben Sie etwas. Geben Sie \"/\" für Befehle ein", "Write...": "\"Schreiben...\"", "Column count": "Spaltenanzahl", - "{{count}} Columns": "{count, plural, one {# Spalte} other {# Spalten}}", + "{{count}} Columns": "{{count}} Spalten", "Equal columns": "Gleich breite Spalten", "Left sidebar": "Linke Seitenleiste", "Right sidebar": "Rechte Seitenleiste", From 09c69d7a0f21085fbd0c89d6d298537e6378d85d Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Fri, 1 May 2026 00:49:31 +0100 Subject: [PATCH 12/63] feat: properly preserve table width (#2143) --- .../editor/extensions/markdown-clipboard.ts | 93 ++++++++++++++- .../import/services/import.service.ts | 6 +- .../import/utils/import-formatter.ts | 24 +++- .../integrations/import/utils/table-utils.ts | 107 ++++++++++++++++++ 4 files changed, 225 insertions(+), 5 deletions(-) create mode 100644 apps/server/src/integrations/import/utils/table-utils.ts diff --git a/apps/client/src/features/editor/extensions/markdown-clipboard.ts b/apps/client/src/features/editor/extensions/markdown-clipboard.ts index 230798c50..bebb567ab 100644 --- a/apps/client/src/features/editor/extensions/markdown-clipboard.ts +++ b/apps/client/src/features/editor/extensions/markdown-clipboard.ts @@ -80,10 +80,12 @@ export const MarkdownClipboard = Extension.create({ const { from, to } = view.state.selection; const parsed = markdownToHtml(text.replace(/\n+$/, "")); + const body = elementFromString(parsed); + normalizeTableColumnWidths(body); const contentNodes = DOMParser.fromSchema( this.editor.schema, - ).parseSlice(elementFromString(parsed), { + ).parseSlice(body, { preserveWhitespace: true, }); @@ -137,3 +139,92 @@ function elementFromString(value) { return new window.DOMParser().parseFromString(wrappedValue, "text/html").body; } + +const DEFAULT_PASTE_COL_WIDTH_PX = 150; + +function parsePixelWidth(el: Element): number | null { + const attr = el.getAttribute("width"); + if (attr) { + const n = parseInt(attr, 10); + if (Number.isFinite(n) && n > 0) return n; + } + const style = el.getAttribute("style") || ""; + const m = style.match(/(?:^|;)\s*width\s*:\s*([\d.]+)\s*px/i); + if (m) { + const n = parseInt(m[1], 10); + if (Number.isFinite(n) && n > 0) return n; + } + return null; +} + +function getFirstRow(table: Element): Element | null { + const tbodyRow = table.querySelector(":scope > tbody > tr"); + if (tbodyRow) return tbodyRow; + const theadRow = table.querySelector(":scope > thead > tr"); + if (theadRow) return theadRow; + return table.querySelector(":scope > tr"); +} + +function deriveColumnWidths(table: Element): (number | null)[] | null { + const cols = table.querySelectorAll(":scope > colgroup > col"); + if (cols.length > 0) { + const widths: (number | null)[] = []; + cols.forEach((col) => widths.push(parsePixelWidth(col))); + if (widths.some((w) => w !== null)) return widths; + } + + const firstRow = getFirstRow(table); + if (!firstRow) return null; + + const widths: (number | null)[] = []; + Array.from(firstRow.children) + .filter((c) => c.tagName === "TD" || c.tagName === "TH") + .forEach((cell) => { + const colspan = parseInt(cell.getAttribute("colspan") || "1", 10) || 1; + const w = parsePixelWidth(cell); + for (let i = 0; i < colspan; i++) { + widths.push(w !== null ? Math.round(w / colspan) : null); + } + }); + if (widths.length === 0 || widths.every((w) => w === null)) return null; + return widths; +} + +// Mirror of server normalizeTableColumnWidths (see import/utils/table-utils.ts): +// markdown source has no widths, so without this every pasted table renders +// at table-layout:fixed/100% and squashes columns to fit the editor instead of +// letting .tableWrapper's overflow-x: auto scroll. +export function normalizeTableColumnWidths(root: Element): void { + root.querySelectorAll("table").forEach((table) => { + const firstRow = getFirstRow(table); + if (!firstRow) return; + + let colWidths = deriveColumnWidths(table); + if (!colWidths) { + let count = 0; + Array.from(firstRow.children) + .filter((c) => c.tagName === "TD" || c.tagName === "TH") + .forEach((cell) => { + count += parseInt(cell.getAttribute("colspan") || "1", 10) || 1; + }); + if (count === 0) return; + colWidths = new Array(count).fill(DEFAULT_PASTE_COL_WIDTH_PX); + } + + let col = 0; + Array.from(firstRow.children) + .filter((c) => c.tagName === "TD" || c.tagName === "TH") + .forEach((cell) => { + if (cell.getAttribute("colwidth")) { + col += parseInt(cell.getAttribute("colspan") || "1", 10) || 1; + return; + } + const colspan = parseInt(cell.getAttribute("colspan") || "1", 10) || 1; + const slice = colWidths!.slice(col, col + colspan); + col += colspan; + if (slice.length === 0 || slice.every((w) => w === null)) return; + const values = slice.map((w) => (w == null ? 100 : w)); + cell.setAttribute("colwidth", values.join(",")); + }); + }); +} diff --git a/apps/server/src/integrations/import/services/import.service.ts b/apps/server/src/integrations/import/services/import.service.ts index 66c575850..0eb3ae40d 100644 --- a/apps/server/src/integrations/import/services/import.service.ts +++ b/apps/server/src/integrations/import/services/import.service.ts @@ -29,6 +29,8 @@ import { InjectQueue } from '@nestjs/bullmq'; import { Queue } from 'bullmq'; import { QueueJob, QueueName } from '../../queue/constants'; import { ModuleRef } from '@nestjs/core'; +import { load } from 'cheerio'; +import { normalizeImportHtml } from '../utils/import-formatter'; @Injectable() export class ImportService { @@ -136,7 +138,9 @@ export class ImportService { async processHTML(htmlInput: string): Promise { try { - return htmlToJson(htmlInput); + const $ = load(htmlInput); + normalizeImportHtml($, $.root()); + return htmlToJson($.html() || ''); } catch (err) { throw err; } diff --git a/apps/server/src/integrations/import/utils/import-formatter.ts b/apps/server/src/integrations/import/utils/import-formatter.ts index 3b0738a54..0333b75e7 100644 --- a/apps/server/src/integrations/import/utils/import-formatter.ts +++ b/apps/server/src/integrations/import/utils/import-formatter.ts @@ -5,6 +5,7 @@ import { v7 } from 'uuid'; import { InsertableBacklink } from '@docmost/db/types/entity.types'; import { Cheerio, CheerioAPI, load } from 'cheerio'; import slugify from '@sindresorhus/slugify'; +import { normalizeTableColumnWidths } from './table-utils'; // Check if text contains Unicode characters (for emojis/icons) function isUnicodeCharacter(text: string): boolean { @@ -51,9 +52,7 @@ export async function formatImportHtml(opts: { } } - notionFormatter($, $root); - xwikiFormatter($, $root); - defaultHtmlFormatter($, $root); + normalizeImportHtml($, $root); const backlinks = await rewriteInternalLinksToMentionHtml( $, @@ -73,6 +72,23 @@ export async function formatImportHtml(opts: { }; } +/** + * Contextless HTML cleanup shared by every import path. + * - notionFormatter: no-op on non-Notion HTML (class-selector-based). + * - xwikiFormatter: no-op on non-XWiki HTML (looks for #xwikicontent). + * - defaultHtmlFormatter: table column widths + provider auto-embeds. + * + * Does NOT run rewriteInternalLinksToMentionHtml — that requires zip context. + */ +export function normalizeImportHtml( + $: CheerioAPI, + $root: Cheerio, +): void { + notionFormatter($, $root); + xwikiFormatter($, $root); + defaultHtmlFormatter($, $root); +} + export function xwikiFormatter($: CheerioAPI, $root: Cheerio) { const $content = $root.find('#xwikicontent'); if ($content.length) { @@ -82,6 +98,8 @@ export function xwikiFormatter($: CheerioAPI, $root: Cheerio) { } export function defaultHtmlFormatter($: CheerioAPI, $root: Cheerio) { + normalizeTableColumnWidths($, $root); + $root.find('a[href]').each((_, el) => { const $el = $(el); const url = $el.attr('href')!; diff --git a/apps/server/src/integrations/import/utils/table-utils.ts b/apps/server/src/integrations/import/utils/table-utils.ts new file mode 100644 index 000000000..8b5240a0e --- /dev/null +++ b/apps/server/src/integrations/import/utils/table-utils.ts @@ -0,0 +1,107 @@ +import { CheerioAPI, Cheerio } from 'cheerio'; + +const DEFAULT_IMPORT_COL_WIDTH_PX = 150; + +/** + * Extracts a pixel-integer width from either the `width` attribute or + * `style="width: Npx"` on a //. Returns null when absent, + * non-numeric, or a non-px unit (em, %). + */ +function parsePixelWidth(el: Cheerio): number | null { + const attr = el.attr('width'); + if (attr) { + const n = parseInt(attr, 10); + if (Number.isFinite(n) && n > 0) return n; + } + const style = el.attr('style') || ''; + const m = style.match(/(?:^|;)\s*width\s*:\s*([\d.]+)\s*px/i); + if (m) { + const n = parseInt(m[1], 10); + if (Number.isFinite(n) && n > 0) return n; + } + return null; +} + +/** + * Derives per-column widths for a table, in visual column order. + * Priority: → first-row cells' own width style. + * Returns an array of length = number of columns, with null entries + * for columns whose width couldn't be determined. + */ +function deriveColumnWidths( + $: CheerioAPI, + table: Cheerio, +): (number | null)[] | null { + const cols = table.find('> colgroup > col'); + if (cols.length > 0) { + const widths: (number | null)[] = []; + cols.each(function () { + widths.push(parsePixelWidth($(this))); + }); + if (widths.some((w) => w !== null)) return widths; + } + + // Fallback: first row's cells. + const firstRow = table.find('> tbody > tr, > thead > tr, > tr').first(); + if (!firstRow.length) return null; + + const widths: (number | null)[] = []; + firstRow.children('td, th').each(function () { + const cell = $(this); + const colspan = parseInt(cell.attr('colspan') || '1', 10) || 1; + const w = parsePixelWidth(cell); + for (let i = 0; i < colspan; i++) { + widths.push(w !== null ? Math.round(w / colspan) : null); + } + }); + if (widths.every((w) => w === null)) return null; + return widths; +} + +/** + * Apply colwidth attributes to the first row of each table based on + * derived column widths. Accounts for colspan. Idempotent — re-running + * on already-normalized markup is a no-op. + * + * This lives upstream of tiptap's generateJSON: tiptap reads + * `colwidth="N[,N...]"` on / to build the runtime . + */ +export function normalizeTableColumnWidths( + $: CheerioAPI, + $root: Cheerio, +): void { + $root.find('table').each(function () { + const table = $(this); + const firstRow = table.find('> tbody > tr, > thead > tr, > tr').first(); + if (!firstRow.length) return; + + let colWidths = deriveColumnWidths($, table); + if (!colWidths) { + // No widths anywhere (e.g. markdown-sourced tables). Apply a default + // per-column width so the table's intrinsic width can exceed the + // editor container, letting .tableWrapper's overflow-x: auto scroll + // instead of cramming columns into the available width. + let count = 0; + firstRow.children('td, th').each(function () { + count += parseInt($(this).attr('colspan') || '1', 10) || 1; + }); + if (count === 0) return; + colWidths = new Array(count).fill(DEFAULT_IMPORT_COL_WIDTH_PX); + } + + let col = 0; + firstRow.children('td, th').each(function () { + const cell = $(this); + if (cell.attr('colwidth')) { + col += parseInt(cell.attr('colspan') || '1', 10) || 1; + return; + } + const colspan = parseInt(cell.attr('colspan') || '1', 10) || 1; + const slice = colWidths.slice(col, col + colspan); + col += colspan; + if (slice.length === 0 || slice.every((w) => w === null)) return; + const values = slice.map((w) => (w == null ? 100 : w)); + cell.attr('colwidth', values.join(',')); + }); + }); +} From a0aea43e25035b4f4aa24608674c10c8178f8d63 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Fri, 1 May 2026 11:47:03 +0100 Subject: [PATCH 13/63] feat(saml): allow disabling RequestedAuthnContext via env var Adds SAML_DISABLE_REQUESTED_AUTHN_CONTEXT env var, passed through to the SAML strategy's disableRequestedAuthnContext option. Defaults to existing behavior (element sent). Set to true to omit the element when the IdP authenticates the user with a method that does not match (e.g. MFA, FIDO, passwordless), which would otherwise cause AADSTS75011 with Microsoft Entra ID. --- apps/server/src/ee | 2 +- .../src/integrations/environment/environment.service.ts | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/server/src/ee b/apps/server/src/ee index 4101fc427..fabe27298 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit 4101fc427b785e2711c0f608c377d641a2e4be78 +Subproject commit fabe2729879e0543518f0c42bfdb3b403afe3c4a diff --git a/apps/server/src/integrations/environment/environment.service.ts b/apps/server/src/integrations/environment/environment.service.ts index af35e9346..f0b548ab7 100644 --- a/apps/server/src/integrations/environment/environment.service.ts +++ b/apps/server/src/integrations/environment/environment.service.ts @@ -304,4 +304,11 @@ export class EnvironmentService { getClickHouseUrl(): string { return this.configService.get('CLICKHOUSE_URL'); } + + getSamlDisableRequestedAuthnContext(): boolean { + const disabled = this.configService + .get('SAML_DISABLE_REQUESTED_AUTHN_CONTEXT', 'false') + .toLowerCase(); + return disabled === 'true'; + } } From 1d2486455fb10678ca178257ad0b6b0186e7b522 Mon Sep 17 00:00:00 2001 From: Sarthak Chaturvedi <84394327+mayhemking007@users.noreply.github.com> Date: Fri, 1 May 2026 18:28:51 +0530 Subject: [PATCH 14/63] fix: prevent browser tab fallback in editor (#2123) --- apps/client/src/features/editor/page-editor.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/client/src/features/editor/page-editor.tsx b/apps/client/src/features/editor/page-editor.tsx index 30ccc2e48..c8c07bc2e 100644 --- a/apps/client/src/features/editor/page-editor.tsx +++ b/apps/client/src/features/editor/page-editor.tsx @@ -236,6 +236,14 @@ export default function PageEditor({ event.preventDefault(); return true; } + if (event.key === "Tab") { + const editor = editorRef.current; + if (!editor) return false; + event.preventDefault(); + return editor.view.someProp("handleKeyDown", (f) => + f(editor.view, event) + ); + } if (platformModifierKey(event) && event.code === "KeyK") { searchSpotlight.open(); return true; From 641ce142dfe229865b1efa130116e851c38c1eb6 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Fri, 1 May 2026 14:53:30 +0100 Subject: [PATCH 15/63] feat(ee): SCIM (#1347) * SCIM - init (EE) * accept db transaction * sync * Content parser support for scim+json * patch scimmy * sync * return early if userIds is empty * sync * SCIM db table * fixes * scim tokens * backfill * feat(audit): add scim token events * rename scim migration * fix * fix translation * cleanup --- .../public/locales/en-US/translation.json | 34 ++++- .../layouts/global/global-app-shell.tsx | 4 +- .../components/settings/settings-queries.tsx | 8 + .../components/settings/settings-sidebar.tsx | 6 +- .../components/api-key-created-modal.tsx | 7 +- .../components/create-api-key-modal.tsx | 2 +- .../components/revoke-api-key-modal.tsx | 6 +- .../components/update-api-key-modal.tsx | 2 +- .../src/ee/api-key/queries/api-key-query.ts | 6 +- .../src/ee/audit/lib/audit-event-labels.ts | 12 ++ .../components/create-scim-token-modal.tsx | 78 ++++++++++ .../src/ee/scim/components/enable-scim.tsx | 55 +++++++ .../components/revoke-scim-token-modal.tsx | 61 ++++++++ .../components/scim-token-created-modal.tsx | 69 +++++++++ .../ee/scim/components/scim-token-table.tsx | 130 ++++++++++++++++ .../src/ee/scim/components/scim-url-panel.tsx | 30 ++++ .../components/update-scim-token-modal.tsx | 77 ++++++++++ apps/client/src/ee/scim/index.ts | 2 + .../src/ee/scim/queries/scim-token-query.ts | 96 ++++++++++++ .../ee/scim/services/scim-token-service.ts | 34 +++++ .../src/ee/scim/types/scim-token.types.ts | 27 ++++ .../security/components/sso-provider-list.tsx | 4 +- .../client/src/ee/security/pages/security.tsx | 143 +++++++++++++++++- .../workspace/types/workspace.types.ts | 1 + apps/server/package.json | 1 + apps/server/src/common/events/audit-events.ts | 6 + apps/server/src/common/helpers/utils.ts | 2 +- .../core/group/services/group-user.service.ts | 15 +- .../src/core/group/services/group.service.ts | 5 +- .../workspace/dto/update-workspace.dto.ts | 4 + .../workspace/services/workspace.service.ts | 12 +- .../migrations/20260501T092214-scim.ts | 110 ++++++++++++++ .../src/database/repos/group/group.repo.ts | 44 ++++-- .../src/database/repos/user/user.repo.ts | 4 + .../repos/workspace/workspace.repo.ts | 1 + apps/server/src/database/types/db.d.ts | 19 +++ .../server/src/database/types/entity.types.ts | 6 + apps/server/src/ee | 2 +- apps/server/src/main.ts | 16 ++ package.json | 3 +- patches/@tiptap__core.patch | 105 ------------- patches/scimmy@1.3.5.patch | 23 +++ pnpm-lock.yaml | 12 ++ 43 files changed, 1136 insertions(+), 148 deletions(-) create mode 100644 apps/client/src/ee/scim/components/create-scim-token-modal.tsx create mode 100644 apps/client/src/ee/scim/components/enable-scim.tsx create mode 100644 apps/client/src/ee/scim/components/revoke-scim-token-modal.tsx create mode 100644 apps/client/src/ee/scim/components/scim-token-created-modal.tsx create mode 100644 apps/client/src/ee/scim/components/scim-token-table.tsx create mode 100644 apps/client/src/ee/scim/components/scim-url-panel.tsx create mode 100644 apps/client/src/ee/scim/components/update-scim-token-modal.tsx create mode 100644 apps/client/src/ee/scim/index.ts create mode 100644 apps/client/src/ee/scim/queries/scim-token-query.ts create mode 100644 apps/client/src/ee/scim/services/scim-token-service.ts create mode 100644 apps/client/src/ee/scim/types/scim-token.types.ts create mode 100644 apps/server/src/database/migrations/20260501T092214-scim.ts delete mode 100644 patches/@tiptap__core.patch create mode 100644 patches/scimmy@1.3.5.patch diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index 3bfe7c9f0..56709bbe6 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -608,25 +608,21 @@ "Image exceeds 10MB limit.": "Image exceeds 10MB limit.", "Image removed successfully": "Image removed successfully", "API key": "API key", - "API key created successfully": "API key created successfully", "API keys": "API keys", "API management": "API management", - "Are you sure you want to revoke this API key": "Are you sure you want to revoke this API key", - "Create API Key": "Create API Key", "Custom expiration date": "Custom expiration date", "Enter a descriptive token name": "Enter a descriptive token name", "Expiration": "Expiration", "Expired": "Expired", "Expires": "Expires", - "I've saved my API key": "I've saved my API key", "Last use": "Last Used", "No API keys found": "No API keys found", "No expiration": "No expiration", - "Revoke API key": "Revoke API key", "Revoked successfully": "Revoked successfully", "Select expiration date": "Select expiration date", "This action cannot be undone. Any applications using this API key will stop working.": "This action cannot be undone. Any applications using this API key will stop working.", - "Update API key": "Update API key", + "Update": "Update", + "Update {{credential}}": "Update {{credential}}", "Manage API keys for all users in the workspace": "Manage API keys for all users in the workspace", "Restrict API key creation to admins": "Restrict API key creation to admins", "Only admins and owners can create new API keys. Existing member keys will continue to work.": "Only admins and owners can create new API keys. Existing member keys will continue to work.", @@ -880,5 +876,29 @@ "Try a different search term.": "Try a different search term.", "Try again": "Try again", "Untitled chat": "Untitled chat", - "What can I help you with?": "What can I help you with?" + "What can I help you with?": "What can I help you with?", + "Are you sure you want to revoke this {{credential}}": "Are you sure you want to revoke this {{credential}}", + "Automatically provision users and groups from your identity provider via SCIM.": "Automatically provision users and groups from your identity provider via SCIM.", + "Configure your identity provider with this URL to provision users and groups.": "Configure your identity provider with this URL to provision users and groups.", + "Create {{credential}}": "Create {{credential}}", + "{{credential}} created": "{{credential}} created", + "{{credential}} created successfully": "{{credential}} created successfully", + "Created by": "Created by", + "Custom": "Custom", + "Enable SCIM": "Enable SCIM", + "Enter a descriptive name": "Enter a descriptive name", + "I've saved my {{credential}}": "I've saved my {{credential}}", + "Important": "Important", + "Make sure to copy your {{credential}} now. You won't be able to see it again!": "Make sure to copy your {{credential}} now. You won't be able to see it again!", + "Never": "Never", + "Revoke {{credential}}": "Revoke {{credential}}", + "SCIM endpoint URL": "SCIM endpoint URL", + "SCIM provisioning": "SCIM provisioning", + "SCIM takes precedence over SSO group sync while enabled.": "SCIM takes precedence over SSO group sync while enabled.", + "You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.", + "SCIM token": "SCIM token", + "SCIM tokens": "SCIM tokens", + "This action cannot be undone. Your identity provider will stop syncing immediately.": "This action cannot be undone. Your identity provider will stop syncing immediately.", + "Toggle SCIM provisioning": "Toggle SCIM provisioning", + "Token": "Token" } diff --git a/apps/client/src/components/layouts/global/global-app-shell.tsx b/apps/client/src/components/layouts/global/global-app-shell.tsx index 64bd3dde7..6e842a056 100644 --- a/apps/client/src/components/layouts/global/global-app-shell.tsx +++ b/apps/client/src/components/layouts/global/global-app-shell.tsx @@ -116,7 +116,9 @@ export default function GlobalAppShell({ {isSettingsRoute ? ( - {children} + + {children} + ) : ( children )} diff --git a/apps/client/src/components/settings/settings-queries.tsx b/apps/client/src/components/settings/settings-queries.tsx index e9562a858..892857f55 100644 --- a/apps/client/src/components/settings/settings-queries.tsx +++ b/apps/client/src/components/settings/settings-queries.tsx @@ -13,6 +13,7 @@ import { getShares } from "@/features/share/services/share-service.ts"; import { getApiKeys } from "@/ee/api-key"; import { getAuditLogs } from "@/ee/audit/services/audit-service"; import { getVerificationList } from "@/ee/page-verification/services/page-verification-service"; +import { getScimTokens } from "@/ee/scim/services/scim-token-service"; export const prefetchWorkspaceMembers = () => { const params: QueryParams = { limit: 100, query: "" }; @@ -98,3 +99,10 @@ export const prefetchVerifiedPages = () => { queryFn: () => getVerificationList(params), }); }; + +export const prefetchScimTokens = () => { + queryClient.prefetchQuery({ + queryKey: ["scim-token-list", { cursor: undefined }], + queryFn: () => getScimTokens({}), + }); +}; diff --git a/apps/client/src/components/settings/settings-sidebar.tsx b/apps/client/src/components/settings/settings-sidebar.tsx index 90d89d13e..8ea1f59f9 100644 --- a/apps/client/src/components/settings/settings-sidebar.tsx +++ b/apps/client/src/components/settings/settings-sidebar.tsx @@ -31,6 +31,7 @@ import { prefetchBilling, prefetchGroups, prefetchLicense, + prefetchScimTokens, prefetchShares, prefetchSpaces, prefetchSsoProviders, @@ -204,7 +205,10 @@ export default function SettingsSidebar() { } break; case "Security & SSO": - prefetchHandler = prefetchSsoProviders; + prefetchHandler = () => { + prefetchSsoProviders(); + prefetchScimTokens(); + }; break; case "Public sharing": prefetchHandler = prefetchShares; diff --git a/apps/client/src/ee/api-key/components/api-key-created-modal.tsx b/apps/client/src/ee/api-key/components/api-key-created-modal.tsx index 6a01ee3cf..ed44811a7 100644 --- a/apps/client/src/ee/api-key/components/api-key-created-modal.tsx +++ b/apps/client/src/ee/api-key/components/api-key-created-modal.tsx @@ -31,7 +31,7 @@ export function ApiKeyCreatedModal({ @@ -41,7 +41,8 @@ export function ApiKeyCreatedModal({ color="red" > {t( - "Make sure to copy your API key now. You won't be able to see it again!", + "Make sure to copy your {{credential}} now. You won't be able to see it again!", + { credential: t("API key") }, )} @@ -64,7 +65,7 @@ export function ApiKeyCreatedModal({ diff --git a/apps/client/src/ee/api-key/components/create-api-key-modal.tsx b/apps/client/src/ee/api-key/components/create-api-key-modal.tsx index ab19552c5..0b93c080b 100644 --- a/apps/client/src/ee/api-key/components/create-api-key-modal.tsx +++ b/apps/client/src/ee/api-key/components/create-api-key-modal.tsx @@ -105,7 +105,7 @@ export function CreateApiKeyModal({
handleSubmit(values))}> diff --git a/apps/client/src/ee/api-key/components/revoke-api-key-modal.tsx b/apps/client/src/ee/api-key/components/revoke-api-key-modal.tsx index 3092ead42..95651a4e0 100644 --- a/apps/client/src/ee/api-key/components/revoke-api-key-modal.tsx +++ b/apps/client/src/ee/api-key/components/revoke-api-key-modal.tsx @@ -30,12 +30,14 @@ export function RevokeApiKeyModal({ - {t("Are you sure you want to revoke this API key")}{" "} + {t("Are you sure you want to revoke this {{credential}}", { + credential: t("API key"), + })}{" "} {apiKey?.name}? diff --git a/apps/client/src/ee/api-key/components/update-api-key-modal.tsx b/apps/client/src/ee/api-key/components/update-api-key-modal.tsx index e4370eac7..0e66d680e 100644 --- a/apps/client/src/ee/api-key/components/update-api-key-modal.tsx +++ b/apps/client/src/ee/api-key/components/update-api-key-modal.tsx @@ -53,7 +53,7 @@ export function UpdateApiKeyModal({ handleSubmit(values))}> diff --git a/apps/client/src/ee/api-key/queries/api-key-query.ts b/apps/client/src/ee/api-key/queries/api-key-query.ts index 75f2d3514..f27492da8 100644 --- a/apps/client/src/ee/api-key/queries/api-key-query.ts +++ b/apps/client/src/ee/api-key/queries/api-key-query.ts @@ -63,7 +63,11 @@ export function useCreateApiKeyMutation() { return useMutation({ mutationFn: (data) => createApiKey(data), onSuccess: () => { - notifications.show({ message: t("API key created successfully") }); + notifications.show({ + message: t("{{credential}} created successfully", { + credential: t("API key"), + }), + }); queryClient.invalidateQueries({ predicate: (item) => ["api-key-list"].includes(item.queryKey[0] as string), diff --git a/apps/client/src/ee/audit/lib/audit-event-labels.ts b/apps/client/src/ee/audit/lib/audit-event-labels.ts index 76d08295a..7fc55b3d0 100644 --- a/apps/client/src/ee/audit/lib/audit-event-labels.ts +++ b/apps/client/src/ee/audit/lib/audit-event-labels.ts @@ -33,6 +33,10 @@ export const auditEventLabels: Record = { "api_key.updated": "Updated API key", "api_key.deleted": "Deleted API key", + "scim_token.created": "Created SCIM token", + "scim_token.updated": "Updated SCIM token", + "scim_token.deleted": "Deleted SCIM token", + "space.created": "Created space", "space.updated": "Updated space", "space.deleted": "Deleted space", @@ -174,6 +178,14 @@ export const eventFilterOptions: EventGroup[] = [ { value: "api_key.deleted", label: "Deleted API key" }, ], }, + { + group: "SCIM token", + items: [ + { value: "scim_token.created", label: "Created SCIM token" }, + { value: "scim_token.updated", label: "Updated SCIM token" }, + { value: "scim_token.deleted", label: "Deleted SCIM token" }, + ], + }, { group: "License", items: [ diff --git a/apps/client/src/ee/scim/components/create-scim-token-modal.tsx b/apps/client/src/ee/scim/components/create-scim-token-modal.tsx new file mode 100644 index 000000000..c0dfa35c3 --- /dev/null +++ b/apps/client/src/ee/scim/components/create-scim-token-modal.tsx @@ -0,0 +1,78 @@ +import { Modal, TextInput, Button, Group, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { zod4Resolver } from "mantine-form-zod-resolver"; +import { z } from "zod/v4"; +import { useTranslation } from "react-i18next"; +import { useCreateScimTokenMutation } from "@/ee/scim/queries/scim-token-query"; +import { IScimToken } from "@/ee/scim/types/scim-token.types"; + +interface CreateScimTokenModalProps { + opened: boolean; + onClose: () => void; + onSuccess: (response: IScimToken) => void; +} + +const formSchema = z.object({ + name: z.string().min(1, "Name is required"), +}); +type FormValues = z.infer; + +export function CreateScimTokenModal({ + opened, + onClose, + onSuccess, +}: CreateScimTokenModalProps) { + const { t } = useTranslation(); + const createMutation = useCreateScimTokenMutation(); + + const form = useForm({ + validate: zod4Resolver(formSchema), + initialValues: { name: "" }, + }); + + const handleSubmit = async (data: FormValues) => { + try { + const created = await createMutation.mutateAsync({ name: data.name }); + onSuccess(created); + form.reset(); + onClose(); + } catch (err) { + // + } + }; + + const handleClose = () => { + form.reset(); + onClose(); + }; + + return ( + + handleSubmit(values))}> + + + + + + + + + + + ); +} diff --git a/apps/client/src/ee/scim/components/enable-scim.tsx b/apps/client/src/ee/scim/components/enable-scim.tsx new file mode 100644 index 000000000..0f8204ebc --- /dev/null +++ b/apps/client/src/ee/scim/components/enable-scim.tsx @@ -0,0 +1,55 @@ +import { Group, Text, Switch, Tooltip } from "@mantine/core"; +import { useAtom } from "jotai"; +import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts"; +import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { updateWorkspace } from "@/features/workspace/services/workspace-service.ts"; +import { notifications } from "@mantine/notifications"; +import { useHasFeature } from "@/ee/hooks/use-feature.ts"; +import { Feature } from "@/ee/features.ts"; +import { useUpgradeLabel } from "@/ee/hooks/use-upgrade-label.ts"; + +export default function EnableScim() { + const { t } = useTranslation(); + const [workspace, setWorkspace] = useAtom(workspaceAtom); + const [checked, setChecked] = useState(workspace?.isScimEnabled ?? false); + const hasAccess = useHasFeature(Feature.SCIM); + const upgradeLabel = useUpgradeLabel(); + + const handleChange = async (event: React.ChangeEvent) => { + const value = event.currentTarget.checked; + try { + const updatedWorkspace = await updateWorkspace({ isScimEnabled: value }); + setChecked(value); + setWorkspace(updatedWorkspace); + } catch (err) { + notifications.show({ + message: err?.response?.data?.message, + color: "red", + }); + } + }; + + return ( + +
+ {t("Enable SCIM")} + + {t( + "Automatically provision users and groups from your identity provider via SCIM.", + )} + +
+ + + + +
+ ); +} diff --git a/apps/client/src/ee/scim/components/revoke-scim-token-modal.tsx b/apps/client/src/ee/scim/components/revoke-scim-token-modal.tsx new file mode 100644 index 000000000..c69878459 --- /dev/null +++ b/apps/client/src/ee/scim/components/revoke-scim-token-modal.tsx @@ -0,0 +1,61 @@ +import { Modal, Text, Button, Group, Stack } from "@mantine/core"; +import { useTranslation } from "react-i18next"; +import { useRevokeScimTokenMutation } from "@/ee/scim/queries/scim-token-query"; +import { IScimToken } from "@/ee/scim/types/scim-token.types"; + +interface RevokeScimTokenModalProps { + opened: boolean; + onClose: () => void; + scimToken: IScimToken | null; +} + +export function RevokeScimTokenModal({ + opened, + onClose, + scimToken, +}: RevokeScimTokenModalProps) { + const { t } = useTranslation(); + const revokeMutation = useRevokeScimTokenMutation(); + + const handleRevoke = async () => { + if (!scimToken) return; + await revokeMutation.mutateAsync({ tokenId: scimToken.id }); + onClose(); + }; + + return ( + + + + {t("Are you sure you want to revoke this {{credential}}", { + credential: t("SCIM token"), + })}{" "} + {scimToken?.name}? + + + {t( + "This action cannot be undone. Your identity provider will stop syncing immediately.", + )} + + + + + + + + + ); +} diff --git a/apps/client/src/ee/scim/components/scim-token-created-modal.tsx b/apps/client/src/ee/scim/components/scim-token-created-modal.tsx new file mode 100644 index 000000000..591a30e39 --- /dev/null +++ b/apps/client/src/ee/scim/components/scim-token-created-modal.tsx @@ -0,0 +1,69 @@ +import { + Modal, + Text, + Stack, + Alert, + Group, + Button, + TextInput, +} from "@mantine/core"; +import { IconAlertTriangle } from "@tabler/icons-react"; +import { useTranslation } from "react-i18next"; +import CopyTextButton from "@/components/common/copy.tsx"; +import { IScimToken } from "@/ee/scim/types/scim-token.types"; + +interface ScimTokenCreatedModalProps { + opened: boolean; + onClose: () => void; + scimToken: IScimToken | null; +} + +export function ScimTokenCreatedModal({ + opened, + onClose, + scimToken, +}: ScimTokenCreatedModalProps) { + const { t } = useTranslation(); + if (!scimToken) return null; + + return ( + + + } + title={t("Important")} + color="red" + > + {t( + "Make sure to copy your {{credential}} now. You won't be able to see it again!", + { credential: t("SCIM token") }, + )} + + +
+ + {t("SCIM token")} + + + + + +
+ + +
+
+ ); +} diff --git a/apps/client/src/ee/scim/components/scim-token-table.tsx b/apps/client/src/ee/scim/components/scim-token-table.tsx new file mode 100644 index 000000000..81b596ee7 --- /dev/null +++ b/apps/client/src/ee/scim/components/scim-token-table.tsx @@ -0,0 +1,130 @@ +import { ActionIcon, Group, Menu, Table, Text } from "@mantine/core"; +import { IconDots, IconEdit, IconTrash } from "@tabler/icons-react"; +import { format } from "date-fns"; +import { useTranslation } from "react-i18next"; +import { CustomAvatar } from "@/components/ui/custom-avatar.tsx"; +import React from "react"; +import NoTableResults from "@/components/common/no-table-results"; +import { IScimToken } from "@/ee/scim/types/scim-token.types"; + +interface ScimTokenTableProps { + tokens: IScimToken[]; + isLoading?: boolean; + onUpdate?: (token: IScimToken) => void; + onRevoke?: (token: IScimToken) => void; +} + +export function ScimTokenTable({ + tokens, + isLoading, + onUpdate, + onRevoke, +}: ScimTokenTableProps) { + const { t } = useTranslation(); + + const formatDate = (date: Date | string | null) => { + if (!date) return t("Never"); + return format(new Date(date), "MMM dd, yyyy"); + }; + + return ( + + + + + {t("Name")} + {t("Token")} + {t("Created by")} + {t("Last used")} + {t("Created")} + + + + + + {tokens && tokens.length > 0 ? ( + tokens.map((token) => ( + + + + {token.name} + + + + + + ••••{token.tokenLastFour} + + + + {token.creator ? ( + + + + + {token.creator.name} + + + + ) : ( + + + — + + + )} + + + + {formatDate(token.lastUsedAt)} + + + + + + {formatDate(token.createdAt)} + + + + + + + + + + + + {onUpdate && ( + } + onClick={() => onUpdate(token)} + > + {t("Rename")} + + )} + {onRevoke && ( + } + color="red" + onClick={() => onRevoke(token)} + > + {t("Revoke")} + + )} + + + + + )) + ) : ( + + )} + +
+
+ ); +} diff --git a/apps/client/src/ee/scim/components/scim-url-panel.tsx b/apps/client/src/ee/scim/components/scim-url-panel.tsx new file mode 100644 index 000000000..6aa78820c --- /dev/null +++ b/apps/client/src/ee/scim/components/scim-url-panel.tsx @@ -0,0 +1,30 @@ +import { Group, Stack, Text, TextInput } from "@mantine/core"; +import { useTranslation } from "react-i18next"; +import CopyTextButton from "@/components/common/copy.tsx"; + +export function ScimUrlPanel() { + const { t } = useTranslation(); + const scimUrl = `${window.location.origin}/api/scim/v2`; + + return ( + + + {t("SCIM endpoint URL")} + + + {t( + "Configure your identity provider with this URL to provision users and groups.", + )} + + + + + + + ); +} diff --git a/apps/client/src/ee/scim/components/update-scim-token-modal.tsx b/apps/client/src/ee/scim/components/update-scim-token-modal.tsx new file mode 100644 index 000000000..104e215ff --- /dev/null +++ b/apps/client/src/ee/scim/components/update-scim-token-modal.tsx @@ -0,0 +1,77 @@ +import { Modal, TextInput, Button, Group, Stack } from "@mantine/core"; +import { useForm } from "@mantine/form"; +import { zod4Resolver } from "mantine-form-zod-resolver"; +import { z } from "zod/v4"; +import { useTranslation } from "react-i18next"; +import { useEffect } from "react"; +import { useUpdateScimTokenMutation } from "@/ee/scim/queries/scim-token-query"; +import { IScimToken } from "@/ee/scim/types/scim-token.types"; + +const formSchema = z.object({ + name: z.string().min(1, "Name is required"), +}); +type FormValues = z.infer; + +interface UpdateScimTokenModalProps { + opened: boolean; + onClose: () => void; + scimToken: IScimToken | null; +} + +export function UpdateScimTokenModal({ + opened, + onClose, + scimToken, +}: UpdateScimTokenModalProps) { + const { t } = useTranslation(); + const updateMutation = useUpdateScimTokenMutation(); + + const form = useForm({ + validate: zod4Resolver(formSchema), + initialValues: { name: "" }, + }); + + useEffect(() => { + if (opened && scimToken) { + form.setValues({ name: scimToken.name }); + } + }, [opened, scimToken]); + + const handleSubmit = async (data: FormValues) => { + if (!scimToken) return; + await updateMutation.mutateAsync({ + tokenId: scimToken.id, + name: data.name, + }); + onClose(); + }; + + return ( + +
handleSubmit(values))}> + + + + + + + + +
+
+ ); +} diff --git a/apps/client/src/ee/scim/index.ts b/apps/client/src/ee/scim/index.ts new file mode 100644 index 000000000..e246200d0 --- /dev/null +++ b/apps/client/src/ee/scim/index.ts @@ -0,0 +1,2 @@ +export * from "./types/scim-token.types"; +export * from "./services/scim-token-service"; diff --git a/apps/client/src/ee/scim/queries/scim-token-query.ts b/apps/client/src/ee/scim/queries/scim-token-query.ts new file mode 100644 index 000000000..999f4d200 --- /dev/null +++ b/apps/client/src/ee/scim/queries/scim-token-query.ts @@ -0,0 +1,96 @@ +import { IPagination, QueryParams } from "@/lib/types.ts"; +import { + keepPreviousData, + useMutation, + useQuery, + useQueryClient, + UseQueryResult, +} from "@tanstack/react-query"; +import { + createScimToken, + getScimTokens, + revokeScimToken, + updateScimToken, +} from "@/ee/scim/services/scim-token-service"; +import { + IScimToken, + ICreateScimTokenRequest, + IRevokeScimTokenRequest, + IUpdateScimTokenRequest, +} from "@/ee/scim/types/scim-token.types"; +import { notifications } from "@mantine/notifications"; +import { useTranslation } from "react-i18next"; + +export function useGetScimTokensQuery( + params?: QueryParams, +): UseQueryResult, Error> { + return useQuery({ + queryKey: ["scim-token-list", params], + queryFn: () => getScimTokens(params), + placeholderData: keepPreviousData, + }); +} + +export function useCreateScimTokenMutation() { + const queryClient = useQueryClient(); + const { t } = useTranslation(); + + return useMutation({ + mutationFn: (data) => createScimToken(data), + onSuccess: () => { + notifications.show({ + message: t("{{credential}} created successfully", { + credential: t("SCIM token"), + }), + }); + queryClient.invalidateQueries({ + predicate: (item) => + ["scim-token-list"].includes(item.queryKey[0] as string), + }); + }, + onError: (error) => { + const errorMessage = error["response"]?.data?.message; + notifications.show({ message: errorMessage, color: "red" }); + }, + }); +} + +export function useUpdateScimTokenMutation() { + const queryClient = useQueryClient(); + const { t } = useTranslation(); + + return useMutation({ + mutationFn: (data) => updateScimToken(data), + onSuccess: () => { + notifications.show({ message: t("Updated successfully") }); + queryClient.invalidateQueries({ + predicate: (item) => + ["scim-token-list"].includes(item.queryKey[0] as string), + }); + }, + onError: (error) => { + const errorMessage = error["response"]?.data?.message; + notifications.show({ message: errorMessage, color: "red" }); + }, + }); +} + +export function useRevokeScimTokenMutation() { + const queryClient = useQueryClient(); + const { t } = useTranslation(); + + return useMutation({ + mutationFn: (data) => revokeScimToken(data), + onSuccess: () => { + notifications.show({ message: t("Revoked successfully") }); + queryClient.invalidateQueries({ + predicate: (item) => + ["scim-token-list"].includes(item.queryKey[0] as string), + }); + }, + onError: (error) => { + const errorMessage = error["response"]?.data?.message; + notifications.show({ message: errorMessage, color: "red" }); + }, + }); +} diff --git a/apps/client/src/ee/scim/services/scim-token-service.ts b/apps/client/src/ee/scim/services/scim-token-service.ts new file mode 100644 index 000000000..27e730358 --- /dev/null +++ b/apps/client/src/ee/scim/services/scim-token-service.ts @@ -0,0 +1,34 @@ +import api from "@/lib/api-client"; +import { + IScimToken, + ICreateScimTokenRequest, + IRevokeScimTokenRequest, + IUpdateScimTokenRequest, +} from "@/ee/scim/types/scim-token.types"; +import { IPagination, QueryParams } from "@/lib/types.ts"; + +export async function getScimTokens( + params?: QueryParams, +): Promise> { + const req = await api.post("/scim-tokens", { ...params }); + return req.data; +} + +export async function createScimToken( + data: ICreateScimTokenRequest, +): Promise { + const req = await api.post("/scim-tokens/create", data); + return req.data; +} + +export async function updateScimToken( + data: IUpdateScimTokenRequest, +): Promise { + await api.post("/scim-tokens/update", data); +} + +export async function revokeScimToken( + data: IRevokeScimTokenRequest, +): Promise { + await api.post("/scim-tokens/revoke", data); +} diff --git a/apps/client/src/ee/scim/types/scim-token.types.ts b/apps/client/src/ee/scim/types/scim-token.types.ts new file mode 100644 index 000000000..076501291 --- /dev/null +++ b/apps/client/src/ee/scim/types/scim-token.types.ts @@ -0,0 +1,27 @@ +import { IUser } from "@/features/user/types/user.types.ts"; + +export interface IScimToken { + id: string; + name: string; + token?: string; + tokenLastFour: string; + isEnabled: boolean; + creatorId: string; + workspaceId: string; + lastUsedAt: string | null; + createdAt: string; + creator?: Partial; +} + +export interface ICreateScimTokenRequest { + name: string; +} + +export interface IUpdateScimTokenRequest { + tokenId: string; + name: string; +} + +export interface IRevokeScimTokenRequest { + tokenId: string; +} diff --git a/apps/client/src/ee/security/components/sso-provider-list.tsx b/apps/client/src/ee/security/components/sso-provider-list.tsx index 7aac7d117..3603f9598 100644 --- a/apps/client/src/ee/security/components/sso-provider-list.tsx +++ b/apps/client/src/ee/security/components/sso-provider-list.tsx @@ -69,8 +69,8 @@ export default function SsoProviderList() { return ( <> - - + +
{t("Name")} diff --git a/apps/client/src/ee/security/pages/security.tsx b/apps/client/src/ee/security/pages/security.tsx index 254809c74..ee6343516 100644 --- a/apps/client/src/ee/security/pages/security.tsx +++ b/apps/client/src/ee/security/pages/security.tsx @@ -1,8 +1,18 @@ import { Helmet } from "react-helmet-async"; import { getAppName, isCloud } from "@/lib/config.ts"; import SettingsTitle from "@/components/settings/settings-title.tsx"; -import { Divider, Title } from "@mantine/core"; -import React from "react"; +import { + Alert, + Button, + Card, + Divider, + Group, + Space, + Title, + Tooltip, +} from "@mantine/core"; +import { IconInfoCircle } from "@tabler/icons-react"; +import React, { useState } from "react"; import useUserRole from "@/hooks/use-user-role.tsx"; import SsoProviderList from "@/ee/security/components/sso-provider-list.tsx"; import CreateSsoProvider from "@/ee/security/components/create-sso-provider.tsx"; @@ -12,16 +22,41 @@ import { useTranslation } from "react-i18next"; import EnforceMfa from "@/ee/security/components/enforce-mfa.tsx"; import DisablePublicSharing from "@/ee/security/components/disable-public-sharing.tsx"; import TrashRetention from "@/ee/security/components/trash-retention.tsx"; - +import { useAtom } from "jotai"; +import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts"; import { useHasFeature } from "@/ee/hooks/use-feature"; import { Feature } from "@/ee/features"; +import { useGetScimTokensQuery } from "@/ee/scim/queries/scim-token-query"; +import { ScimUrlPanel } from "@/ee/scim/components/scim-url-panel"; +import { ScimTokenTable } from "@/ee/scim/components/scim-token-table"; +import { CreateScimTokenModal } from "@/ee/scim/components/create-scim-token-modal"; +import { ScimTokenCreatedModal } from "@/ee/scim/components/scim-token-created-modal"; +import { RevokeScimTokenModal } from "@/ee/scim/components/revoke-scim-token-modal"; +import { UpdateScimTokenModal } from "@/ee/scim/components/update-scim-token-modal"; +import EnableScim from "@/ee/scim/components/enable-scim"; +import { useCursorPaginate } from "@/hooks/use-cursor-paginate"; +import Paginate from "@/components/common/paginate"; +import { IScimToken } from "@/ee/scim/types/scim-token.types"; + +const SCIM_TOKEN_LIMIT = 5; export default function Security() { const { t } = useTranslation(); const { isAdmin } = useUserRole(); const hasCustomSso = useHasFeature(Feature.SSO_CUSTOM); - const hasRetention = useHasFeature(Feature.RETENTION); - const hasSharingControls = useHasFeature(Feature.SHARING_CONTROLS); + const hasScim = useHasFeature(Feature.SCIM); + const [workspace] = useAtom(workspaceAtom); + const isScimEnabled = workspace?.isScimEnabled ?? false; + + const { cursor, goNext, goPrev } = useCursorPaginate(); + const { data: scimData, isLoading: scimLoading } = useGetScimTokensQuery( + hasScim && isScimEnabled ? { cursor } : undefined, + ); + + const [createOpen, setCreateOpen] = useState(false); + const [createdToken, setCreatedToken] = useState(null); + const [updateTarget, setUpdateTarget] = useState(null); + const [revokeTarget, setRevokeTarget] = useState(null); if (!isAdmin) { return null; @@ -45,7 +80,7 @@ export default function Security() { - Single sign-on (SSO) + {t("Single sign-on (SSO)")} @@ -66,6 +101,102 @@ export default function Security() { )} + + {hasScim && ( + <> + + + + {t("SCIM provisioning")} + + + } + color="blue" + variant="light" + mb="md" + > + {t("SCIM takes precedence over SSO group sync while enabled.")} + + + + + + + + + {isScimEnabled && ( + <> + + + + {t("SCIM tokens")} + + + + + + + + + + + + {scimData?.items.length > 0 && ( + goNext(scimData?.meta?.nextCursor)} + onPrev={goPrev} + /> + )} + + setCreateOpen(false)} + onSuccess={setCreatedToken} + /> + + setCreatedToken(null)} + scimToken={createdToken} + /> + + setUpdateTarget(null)} + scimToken={updateTarget} + /> + + setRevokeTarget(null)} + scimToken={revokeTarget} + /> + + )} + + )} ); } diff --git a/apps/client/src/features/workspace/types/workspace.types.ts b/apps/client/src/features/workspace/types/workspace.types.ts index f733f73a0..eda89dd56 100644 --- a/apps/client/src/features/workspace/types/workspace.types.ts +++ b/apps/client/src/features/workspace/types/workspace.types.ts @@ -28,6 +28,7 @@ export interface IWorkspace { trashRetentionDays?: number; restrictApiToAdmins?: boolean; allowMemberTemplates?: boolean; + isScimEnabled?: boolean; } export interface IWorkspaceSettings { diff --git a/apps/server/package.json b/apps/server/package.json index 7c97763b7..794924876 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -111,6 +111,7 @@ "reflect-metadata": "^0.2.2", "rxjs": "^7.8.2", "sanitize-filename": "1.6.3", + "scimmy": "1.3.5", "socket.io": "^4.8.3", "stripe": "^17.7.0", "tlds": "^1.261.0", diff --git a/apps/server/src/common/events/audit-events.ts b/apps/server/src/common/events/audit-events.ts index 955a6ba5a..d8be76f83 100644 --- a/apps/server/src/common/events/audit-events.ts +++ b/apps/server/src/common/events/audit-events.ts @@ -23,6 +23,11 @@ export const AuditEvent = { API_KEY_UPDATED: 'api_key.updated', API_KEY_DELETED: 'api_key.deleted', + // SCIM Tokens + SCIM_TOKEN_CREATED: 'scim_token.created', + SCIM_TOKEN_UPDATED: 'scim_token.updated', + SCIM_TOKEN_DELETED: 'scim_token.deleted', + // Space SPACE_CREATED: 'space.created', SPACE_UPDATED: 'space.updated', @@ -119,6 +124,7 @@ export const AuditResource = { COMMENT: 'comment', SHARE: 'share', API_KEY: 'api_key', + SCIM_TOKEN: 'scim_token', SSO_PROVIDER: 'sso_provider', WORKSPACE_INVITATION: 'workspace_invitation', ATTACHMENT: 'attachment', diff --git a/apps/server/src/common/helpers/utils.ts b/apps/server/src/common/helpers/utils.ts index f65067e1a..21475c143 100644 --- a/apps/server/src/common/helpers/utils.ts +++ b/apps/server/src/common/helpers/utils.ts @@ -110,7 +110,7 @@ export function extractBearerTokenFromHeader( request: FastifyRequest, ): string | undefined { const [type, token] = request.headers.authorization?.split(' ') ?? []; - return type === 'Bearer' ? token : undefined; + return type?.toLowerCase() === 'bearer' ? token : undefined; } /** diff --git a/apps/server/src/core/group/services/group-user.service.ts b/apps/server/src/core/group/services/group-user.service.ts index 58ca8a892..2857f70f8 100644 --- a/apps/server/src/core/group/services/group-user.service.ts +++ b/apps/server/src/core/group/services/group-user.service.ts @@ -7,7 +7,7 @@ import { } from '@nestjs/common'; import { PaginationOptions } from '@docmost/db/pagination/pagination-options'; import { GroupService } from './group.service'; -import { KyselyDB } from '@docmost/db/types/kysely.types'; +import { KyselyDB, KyselyTransaction } from '@docmost/db/types/kysely.types'; import { InjectKysely } from 'nestjs-kysely'; import { GroupUserRepo } from '@docmost/db/repos/group/group-user.repo'; import { SpaceMemberRepo } from '@docmost/db/repos/space/space-member.repo'; @@ -20,6 +20,7 @@ import { AUDIT_SERVICE, IAuditService, } from '../../../integrations/audit/audit.service'; +import { dbOrTx } from '@docmost/db/utils'; @Injectable() export class GroupUserService { @@ -54,17 +55,23 @@ export class GroupUserService { userIds: string[], groupId: string, workspaceId: string, + trx?: KyselyTransaction, ): Promise { - await this.groupService.findAndValidateGroup(groupId, workspaceId); + const db = dbOrTx(this.db, trx); + await this.groupService.findAndValidateGroup(groupId, workspaceId, trx); + + if (userIds.length === 0) return; // make sure we have valid workspace users - const validUsers = await this.db + const validUsers = await db .selectFrom('users') .select(['id', 'name']) .where('users.id', 'in', userIds) .where('users.workspaceId', '=', workspaceId) .execute(); + if (validUsers.length === 0) return; + // prepare users to add to group const groupUsersToInsert = []; for (const user of validUsers) { @@ -75,7 +82,7 @@ export class GroupUserService { } // batch insert new group users - await this.db + await db .insertInto('groupUsers') .values(groupUsersToInsert) .onConflict((oc) => oc.columns(['userId', 'groupId']).doNothing()) diff --git a/apps/server/src/core/group/services/group.service.ts b/apps/server/src/core/group/services/group.service.ts index 838376385..47de46936 100644 --- a/apps/server/src/core/group/services/group.service.ts +++ b/apps/server/src/core/group/services/group.service.ts @@ -216,8 +216,11 @@ export class GroupService { async findAndValidateGroup( groupId: string, workspaceId: string, + trx?: KyselyTransaction, ): Promise { - const group = await this.groupRepo.findById(groupId, workspaceId); + const group = await this.groupRepo.findById(groupId, workspaceId, { + trx, + }); if (!group) { throw new NotFoundException('Group not found'); } diff --git a/apps/server/src/core/workspace/dto/update-workspace.dto.ts b/apps/server/src/core/workspace/dto/update-workspace.dto.ts index a08b1e524..25697a4b9 100644 --- a/apps/server/src/core/workspace/dto/update-workspace.dto.ts +++ b/apps/server/src/core/workspace/dto/update-workspace.dto.ts @@ -41,6 +41,10 @@ export class UpdateWorkspaceDto extends PartialType(CreateWorkspaceDto) { @IsBoolean() mcpEnabled: boolean; + @IsOptional() + @IsBoolean() + isScimEnabled: boolean; + @IsOptional() @IsBoolean() aiChat: boolean; diff --git a/apps/server/src/core/workspace/services/workspace.service.ts b/apps/server/src/core/workspace/services/workspace.service.ts index 726089518..267eb13b7 100644 --- a/apps/server/src/core/workspace/services/workspace.service.ts +++ b/apps/server/src/core/workspace/services/workspace.service.ts @@ -331,7 +331,8 @@ export class WorkspaceService { typeof updateWorkspaceDto.trashRetentionDays !== 'undefined' || typeof updateWorkspaceDto.mcpEnabled !== 'undefined' || typeof updateWorkspaceDto.restrictApiToAdmins !== 'undefined' || - typeof updateWorkspaceDto.allowMemberTemplates !== 'undefined' + typeof updateWorkspaceDto.allowMemberTemplates !== 'undefined' || + typeof updateWorkspaceDto.isScimEnabled !== 'undefined' ) { const ws = await this.db .selectFrom('workspaces') @@ -351,6 +352,14 @@ export class WorkspaceService { } } + if (typeof updateWorkspaceDto.isScimEnabled !== 'undefined') { + if (!this.licenseCheckService.hasFeature(ws.licenseKey, Feature.SCIM, ws.plan)) { + throw new ForbiddenException( + 'This feature requires a valid license', + ); + } + } + if ( typeof updateWorkspaceDto.disablePublicSharing !== 'undefined' || typeof updateWorkspaceDto.trashRetentionDays !== 'undefined' || @@ -535,6 +544,7 @@ export class WorkspaceService { 'enforceSso', 'enforceMfa', 'emailDomains', + 'isScimEnabled', ], updateWorkspaceDto, workspaceBefore, diff --git a/apps/server/src/database/migrations/20260501T092214-scim.ts b/apps/server/src/database/migrations/20260501T092214-scim.ts new file mode 100644 index 000000000..69e4bf566 --- /dev/null +++ b/apps/server/src/database/migrations/20260501T092214-scim.ts @@ -0,0 +1,110 @@ +import { Kysely, sql } from 'kysely'; + +export async function up(db: Kysely): Promise { + await db.schema + .createTable('scim_tokens') + .addColumn('id', 'uuid', (col) => + col.primaryKey().defaultTo(sql`gen_uuid_v7()`), + ) + .addColumn('name', 'varchar', (col) => col.notNull()) + .addColumn('token_hash', 'varchar', (col) => col.notNull()) + .addColumn('token_last_four', 'varchar(4)', (col) => col.notNull()) + .addColumn('last_used_at', 'timestamptz') + .addColumn('is_enabled', 'boolean', (col) => col.notNull().defaultTo(true)) + .addColumn('creator_id', 'uuid', (col) => + col.references('users.id').onDelete('set null'), + ) + .addColumn('workspace_id', 'uuid', (col) => + col.references('workspaces.id').onDelete('cascade').notNull(), + ) + .addColumn('created_at', 'timestamptz', (col) => + col.notNull().defaultTo(sql`now()`), + ) + .addColumn('updated_at', 'timestamptz', (col) => + col.notNull().defaultTo(sql`now()`), + ) + .addColumn('deleted_at', 'timestamptz') + .execute(); + + await db.schema + .createIndex('idx_scim_tokens_token_hash') + .ifNotExists() + .on('scim_tokens') + .column('token_hash') + .execute(); + + await db.schema + .createIndex('idx_scim_tokens_workspace_id') + .ifNotExists() + .on('scim_tokens') + .column('workspace_id') + .execute(); + + await db.schema + .alterTable('users') + .addColumn('scim_external_id', 'text') + .execute(); + + await db.schema + .createIndex('idx_users_workspace_scim_external_id') + .ifNotExists() + .on('users') + .columns(['workspace_id', 'scim_external_id']) + .where('scim_external_id', 'is not', null) + .unique() + .execute(); + + await db.schema + .alterTable('groups') + .addColumn('scim_external_id', 'text') + .execute(); + + await db.schema + .createIndex('idx_groups_workspace_scim_external_id') + .ifNotExists() + .on('groups') + .columns(['workspace_id', 'scim_external_id']) + .where('scim_external_id', 'is not', null) + .unique() + .execute(); + + await db.schema + .alterTable('groups') + .addColumn('is_external', 'boolean', (col) => + col.notNull().defaultTo(false), + ) + .execute(); + + // Backfill: mark all non-default groups as external in workspaces with SSO group sync enabled + await sql` + UPDATE groups SET is_external = true + WHERE is_default = false + AND workspace_id IN ( + SELECT workspace_id FROM auth_providers WHERE group_sync = true + ) + `.execute(db); + + await db.schema + .alterTable('workspaces') + .addColumn('is_scim_enabled', 'boolean', (col) => + col.notNull().defaultTo(false), + ) + .execute(); +} + +export async function down(db: Kysely): Promise { + await db.schema.dropTable('scim_tokens').execute(); + + await db.schema.dropIndex('idx_users_workspace_scim_external_id').execute(); + await db.schema.alterTable('users').dropColumn('scim_external_id').execute(); + + await db.schema.dropIndex('idx_groups_workspace_scim_external_id').execute(); + await db.schema.alterTable('groups').dropColumn('scim_external_id').execute(); + + await db.schema.alterTable('groups').dropColumn('is_external').execute(); + + await db.schema + .alterTable('workspaces') + .dropColumn('is_scim_enabled') + .execute(); +} diff --git a/apps/server/src/database/repos/group/group.repo.ts b/apps/server/src/database/repos/group/group.repo.ts index 3b8c1ea76..219a9077f 100644 --- a/apps/server/src/database/repos/group/group.repo.ts +++ b/apps/server/src/database/repos/group/group.repo.ts @@ -9,7 +9,7 @@ import { } from '@docmost/db/types/entity.types'; import { ExpressionBuilder, sql } from 'kysely'; import { PaginationOptions } from '../../pagination/pagination-options'; -import { DB } from '@docmost/db/types/db'; +import { DB, Groups } from '@docmost/db/types/db'; import { DefaultGroup } from '../../../core/group/dto/create-group.dto'; import { executeWithCursorPagination } from '@docmost/db/pagination/cursor-pagination'; @@ -17,16 +17,34 @@ import { executeWithCursorPagination } from '@docmost/db/pagination/cursor-pagin export class GroupRepo { constructor(@InjectKysely() private readonly db: KyselyDB) {} + private baseFields: Array = [ + 'id', + 'name', + 'description', + 'isDefault', + 'isExternal', + 'creatorId', + 'workspaceId', + 'createdAt', + 'updatedAt', + 'deletedAt', + ]; + async findById( groupId: string, workspaceId: string, - opts?: { includeMemberCount?: boolean; trx?: KyselyTransaction }, + opts?: { + includeMemberCount?: boolean; + includeScimExternalId?: boolean; + trx?: KyselyTransaction; + }, ): Promise { const db = dbOrTx(this.db, opts?.trx); return db .selectFrom('groups') - .selectAll('groups') + .select(this.baseFields) .$if(opts?.includeMemberCount, (qb) => qb.select(this.withMemberCount)) + .$if(opts?.includeScimExternalId, (qb) => qb.select('scimExternalId')) .where('id', '=', groupId) .where('workspaceId', '=', workspaceId) .executeTakeFirst(); @@ -35,13 +53,18 @@ export class GroupRepo { async findByName( groupName: string, workspaceId: string, - opts?: { includeMemberCount?: boolean; trx?: KyselyTransaction }, + opts?: { + includeMemberCount?: boolean; + includeScimExternalId?: boolean; + trx?: KyselyTransaction; + }, ): Promise { const db = dbOrTx(this.db, opts?.trx); return db .selectFrom('groups') - .selectAll('groups') + .select(this.baseFields) .$if(opts?.includeMemberCount, (qb) => qb.select(this.withMemberCount)) + .$if(opts?.includeScimExternalId, (qb) => qb.select('scimExternalId')) .where(sql`LOWER(name)`, '=', sql`LOWER(${groupName})`) .where('workspaceId', '=', workspaceId) .executeTakeFirst(); @@ -51,8 +74,11 @@ export class GroupRepo { updatableGroup: UpdatableGroup, groupId: string, workspaceId: string, + trx?: KyselyTransaction, ): Promise { - await this.db + const db = dbOrTx(this.db, trx); + + await db .updateTable('groups') .set({ ...updatableGroup, updatedAt: new Date() }) .where('id', '=', groupId) @@ -68,7 +94,7 @@ export class GroupRepo { return db .insertInto('groups') .values(insertableGroup) - .returningAll() + .returning(this.baseFields) .executeTakeFirst(); } @@ -80,7 +106,7 @@ export class GroupRepo { return ( db .selectFrom('groups') - .selectAll() + .select(this.baseFields) // .select((eb) => this.withMemberCount(eb)) .where('isDefault', '=', true) .where('workspaceId', '=', workspaceId) @@ -106,7 +132,7 @@ export class GroupRepo { async getGroupsPaginated(workspaceId: string, pagination: PaginationOptions) { let baseQuery = this.db .selectFrom('groups') - .selectAll('groups') + .select(this.baseFields) .select((eb) => this.withMemberCount(eb)) .where('workspaceId', '=', workspaceId); diff --git a/apps/server/src/database/repos/user/user.repo.ts b/apps/server/src/database/repos/user/user.repo.ts index eaaa318ef..6f9f51cf4 100644 --- a/apps/server/src/database/repos/user/user.repo.ts +++ b/apps/server/src/database/repos/user/user.repo.ts @@ -44,6 +44,7 @@ export class UserRepo { opts?: { includePassword?: boolean; includeUserMfa?: boolean; + includeScimExternalId?: boolean; trx?: KyselyTransaction; }, ): Promise { @@ -53,6 +54,7 @@ export class UserRepo { .select(this.baseFields) .$if(opts?.includePassword, (qb) => qb.select('password')) .$if(opts?.includeUserMfa, (qb) => qb.select(this.withUserMfa)) + .$if(opts?.includeScimExternalId, (qb) => qb.select('scimExternalId')) .where('id', '=', userId) .where('workspaceId', '=', workspaceId) .executeTakeFirst(); @@ -64,6 +66,7 @@ export class UserRepo { opts?: { includePassword?: boolean; includeUserMfa?: boolean; + includeScimExternalId?: boolean; trx?: KyselyTransaction; }, ): Promise { @@ -73,6 +76,7 @@ export class UserRepo { .select(this.baseFields) .$if(opts?.includePassword, (qb) => qb.select('password')) .$if(opts?.includeUserMfa, (qb) => qb.select(this.withUserMfa)) + .$if(opts?.includeScimExternalId, (qb) => qb.select('scimExternalId')) .where(sql`LOWER(email)`, '=', sql`LOWER(${email})`) .where('workspaceId', '=', workspaceId) .executeTakeFirst(); diff --git a/apps/server/src/database/repos/workspace/workspace.repo.ts b/apps/server/src/database/repos/workspace/workspace.repo.ts index 4e3990110..408c46ba9 100644 --- a/apps/server/src/database/repos/workspace/workspace.repo.ts +++ b/apps/server/src/database/repos/workspace/workspace.repo.ts @@ -34,6 +34,7 @@ export class WorkspaceRepo { 'plan', 'enforceMfa', 'trashRetentionDays', + 'isScimEnabled', ]; constructor(@InjectKysely() private readonly db: KyselyDB) {} diff --git a/apps/server/src/database/types/db.d.ts b/apps/server/src/database/types/db.d.ts index 0890df93b..ef2c02a00 100644 --- a/apps/server/src/database/types/db.d.ts +++ b/apps/server/src/database/types/db.d.ts @@ -213,7 +213,9 @@ export interface Groups { description: string | null; id: Generated; isDefault: boolean; + isExternal: Generated; name: string; + scimExternalId: string | null; updatedAt: Generated; workspaceId: string; } @@ -338,6 +340,7 @@ export interface Users { name: string | null; password: string | null; role: string | null; + scimExternalId: string | null; settings: Json | null; timezone: string | null; updatedAt: Generated; @@ -381,6 +384,7 @@ export interface Workspaces { enforceMfa: Generated; enforceSso: Generated; hostname: string | null; + isScimEnabled: Generated; id: Generated; licenseKey: string | null; logo: string | null; @@ -410,6 +414,20 @@ export interface Notifications { createdAt: Generated; } +export interface ScimTokens { + createdAt: Generated; + deletedAt: Timestamp | null; + id: Generated; + isEnabled: Generated; + lastUsedAt: Timestamp | null; + name: string; + tokenHash: string; + tokenLastFour: string; + creatorId: string | null; + updatedAt: Generated; + workspaceId: string; +} + export interface Watchers { id: Generated; userId: string; @@ -558,6 +576,7 @@ export interface DB { pageVerifications: PageVerifications; pageVerifiers: PageVerifiers; pages: Pages; + scimTokens: ScimTokens; shares: Shares; spaceMembers: SpaceMembers; spaces: Spaces; diff --git a/apps/server/src/database/types/entity.types.ts b/apps/server/src/database/types/entity.types.ts index 481321bc4..ffac8406d 100644 --- a/apps/server/src/database/types/entity.types.ts +++ b/apps/server/src/database/types/entity.types.ts @@ -29,6 +29,7 @@ import { UserMfa as _UserMFA, UserSessions, ApiKeys, + ScimTokens, Watchers, Audit as _Audit, Templates, @@ -159,6 +160,11 @@ export type ApiKey = Selectable; export type InsertableApiKey = Insertable; export type UpdatableApiKey = Updateable>; +// Scim Tokens +export type ScimToken = Selectable; +export type InsertableScimToken = Insertable; +export type UpdatableScimToken = Updateable>; + // Page Embedding export type PageEmbedding = Selectable; export type InsertablePageEmbedding = Insertable; diff --git a/apps/server/src/ee b/apps/server/src/ee index fabe27298..109829076 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit fabe2729879e0543518f0c42bfdb3b403afe3c4a +Subproject commit 109829076c8d81f6d77836820a5caa63ae8d073f diff --git a/apps/server/src/main.ts b/apps/server/src/main.ts index d47bf547e..7e82b6d92 100644 --- a/apps/server/src/main.ts +++ b/apps/server/src/main.ts @@ -50,6 +50,22 @@ async function bootstrap() { await app.register(fastifyMultipart); await app.register(fastifyCookie); + app + .getHttpAdapter() + .getInstance() + .addContentTypeParser( + 'application/scim+json', + { parseAs: 'string' }, + (_, body, done) => { + try { + const json = JSON.parse(body.toString()); + done(null, json); + } catch (err: any) { + done(err); + } + }, + ); + app .getHttpAdapter() .getInstance() diff --git a/package.json b/package.json index 589721623..cd2fb1279 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,8 @@ "packageManager": "pnpm@10.4.0", "pnpm": { "patchedDependencies": { - "react-arborist@3.4.0": "patches/react-arborist@3.4.0.patch" + "react-arborist@3.4.0": "patches/react-arborist@3.4.0.patch", + "scimmy@1.3.5": "patches/scimmy@1.3.5.patch" }, "overrides": { "prosemirror-changeset": "2.4.0", diff --git a/patches/@tiptap__core.patch b/patches/@tiptap__core.patch deleted file mode 100644 index 58f580c8a..000000000 --- a/patches/@tiptap__core.patch +++ /dev/null @@ -1,105 +0,0 @@ -diff --git a/dist/index.cjs b/dist/index.cjs -index 01d6999642c5ae990083798a1bf0ef87068e4192..891b13c6901f28a6ab413c6dbae0ea726a76a196 100644 ---- a/dist/index.cjs -+++ b/dist/index.cjs -@@ -5463,7 +5463,10 @@ var ResizableNodeView = class { - this.container.classList.remove(this.classNames.resizing); - } - document.removeEventListener("mousemove", this.handleMouseMove); -+ document.removeEventListener("touchmove", this.handleTouchMove); - document.removeEventListener("mouseup", this.handleMouseUp); -+ document.removeEventListener("touchend", this.handleMouseUp); -+ window.removeEventListener("blur", this.handleMouseUp); - document.removeEventListener("keydown", this.handleKeyDown); - document.removeEventListener("keyup", this.handleKeyUp); - }; -@@ -5593,7 +5596,10 @@ var ResizableNodeView = class { - this.container.classList.remove(this.classNames.resizing); - } - document.removeEventListener("mousemove", this.handleMouseMove); -+ document.removeEventListener("touchmove", this.handleTouchMove); - document.removeEventListener("mouseup", this.handleMouseUp); -+ document.removeEventListener("touchend", this.handleMouseUp); -+ window.removeEventListener("blur", this.handleMouseUp); - document.removeEventListener("keydown", this.handleKeyDown); - document.removeEventListener("keyup", this.handleKeyUp); - this.isResizing = false; -@@ -5796,6 +5802,8 @@ var ResizableNodeView = class { - document.addEventListener("mousemove", this.handleMouseMove); - document.addEventListener("touchmove", this.handleTouchMove); - document.addEventListener("mouseup", this.handleMouseUp); -+ document.addEventListener("touchend", this.handleMouseUp); -+ window.addEventListener("blur", this.handleMouseUp); - document.addEventListener("keydown", this.handleKeyDown); - document.addEventListener("keyup", this.handleKeyUp); - } -diff --git a/dist/index.js b/dist/index.js -index 6f357a03b038abeb5ed86967b7fc7c3e5eb1d2d6..2d2742532860821984e1ba82625821504538ebbe 100644 ---- a/dist/index.js -+++ b/dist/index.js -@@ -5330,7 +5330,10 @@ var ResizableNodeView = class { - this.container.classList.remove(this.classNames.resizing); - } - document.removeEventListener("mousemove", this.handleMouseMove); -+ document.removeEventListener("touchmove", this.handleTouchMove); - document.removeEventListener("mouseup", this.handleMouseUp); -+ document.removeEventListener("touchend", this.handleMouseUp); -+ window.removeEventListener("blur", this.handleMouseUp); - document.removeEventListener("keydown", this.handleKeyDown); - document.removeEventListener("keyup", this.handleKeyUp); - }; -@@ -5460,7 +5463,10 @@ var ResizableNodeView = class { - this.container.classList.remove(this.classNames.resizing); - } - document.removeEventListener("mousemove", this.handleMouseMove); -+ document.removeEventListener("touchmove", this.handleTouchMove); - document.removeEventListener("mouseup", this.handleMouseUp); -+ document.removeEventListener("touchend", this.handleMouseUp); -+ window.removeEventListener("blur", this.handleMouseUp); - document.removeEventListener("keydown", this.handleKeyDown); - document.removeEventListener("keyup", this.handleKeyUp); - this.isResizing = false; -@@ -5663,6 +5669,8 @@ var ResizableNodeView = class { - document.addEventListener("mousemove", this.handleMouseMove); - document.addEventListener("touchmove", this.handleTouchMove); - document.addEventListener("mouseup", this.handleMouseUp); -+ document.addEventListener("touchend", this.handleMouseUp); -+ window.addEventListener("blur", this.handleMouseUp); - document.addEventListener("keydown", this.handleKeyDown); - document.addEventListener("keyup", this.handleKeyUp); - } -diff --git a/src/lib/ResizableNodeView.ts b/src/lib/ResizableNodeView.ts -index f13e210b0aa46aefe7c31105deee3d2aa8a26cd5..9bac138dbf17c6ae6c3c129cbedb3a81bd39b60c 100644 ---- a/src/lib/ResizableNodeView.ts -+++ b/src/lib/ResizableNodeView.ts -@@ -523,7 +523,10 @@ export class ResizableNodeView { - } - - document.removeEventListener('mousemove', this.handleMouseMove) -+ document.removeEventListener('touchmove', this.handleTouchMove) - document.removeEventListener('mouseup', this.handleMouseUp) -+ document.removeEventListener('touchend', this.handleMouseUp) -+ window.removeEventListener('blur', this.handleMouseUp) - document.removeEventListener('keydown', this.handleKeyDown) - document.removeEventListener('keyup', this.handleKeyUp) - this.isResizing = false -@@ -774,6 +777,8 @@ export class ResizableNodeView { - document.addEventListener('mousemove', this.handleMouseMove) - document.addEventListener('touchmove', this.handleTouchMove) - document.addEventListener('mouseup', this.handleMouseUp) -+ document.addEventListener('touchend', this.handleMouseUp) -+ window.addEventListener('blur', this.handleMouseUp) - document.addEventListener('keydown', this.handleKeyDown) - document.addEventListener('keyup', this.handleKeyUp) - } -@@ -859,7 +864,10 @@ export class ResizableNodeView { - - // Clean up document-level listeners - document.removeEventListener('mousemove', this.handleMouseMove) -+ document.removeEventListener('touchmove', this.handleTouchMove) - document.removeEventListener('mouseup', this.handleMouseUp) -+ document.removeEventListener('touchend', this.handleMouseUp) -+ window.removeEventListener('blur', this.handleMouseUp) - document.removeEventListener('keydown', this.handleKeyDown) - document.removeEventListener('keyup', this.handleKeyUp) - } diff --git a/patches/scimmy@1.3.5.patch b/patches/scimmy@1.3.5.patch new file mode 100644 index 000000000..fd2060346 --- /dev/null +++ b/patches/scimmy@1.3.5.patch @@ -0,0 +1,23 @@ +diff --git a/dist/cjs/lib/messages.cjs b/dist/cjs/lib/messages.cjs +index e74b8f52137e3267f3d065c4210a1114c4f32dd1..5740606b18851c0ac4f55cfa333152359e0ad135 100644 +--- a/dist/cjs/lib/messages.cjs ++++ b/dist/cjs/lib/messages.cjs +@@ -502,10 +502,15 @@ class PatchOp { + } + } + } +- ++ ++ /** Reason: Commented out to avoid failing patch requests when filters don't match. ++ * Some IdPs send patch paths like `addresses[type eq "work"].country` even if no such address exists. We can't always decide what the end user IdPs send. ++ * Since we manually control patch application, we safely ignore these cases. ++ * example error: "noTarget","detail":"Filter 'addresses[type eq \"work\"].country' does not match any values for 'add' op of operation 5 in PatchOp request body ++ */ + // No targets, bail out! +- if (targets.length === 0 && op !== "remove") +- throw new lib_types.default.Error(400, "noTarget", `Filter '${path}' does not match any values for '${op}' op of operation ${index} in PatchOp request body`); ++ // if (targets.length === 0 && op !== "remove") ++ // throw new lib_types.default.Error(400, "noTarget", `Filter '${path}' does not match any values for '${op}' op of operation ${index} in PatchOp request body`); + + /** + * @typedef {Object} PatchOpDetails diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4ceb29771..3985bc750 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,6 +46,9 @@ patchedDependencies: react-arborist@3.4.0: hash: 419b3b02e24afe928cc006a006f6e906666aff19aa6fd7daaa788ccc2202678a path: patches/react-arborist@3.4.0.patch + scimmy@1.3.5: + hash: 775d80f86830b2c5dd1a250c9802c10f8fc3da3c7898373de5aa0c23993d1673 + path: patches/scimmy@1.3.5.patch importers: @@ -701,6 +704,9 @@ importers: sanitize-filename: specifier: 1.6.3 version: 1.6.3 + scimmy: + specifier: 1.3.5 + version: 1.3.5(patch_hash=775d80f86830b2c5dd1a250c9802c10f8fc3da3c7898373de5aa0c23993d1673) socket.io: specifier: ^4.8.3 version: 4.8.3 @@ -9604,6 +9610,10 @@ packages: resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} engines: {node: '>= 10.13.0'} + scimmy@1.3.5: + resolution: {integrity: sha512-JTrUOoqH1gMH2zZhgk01hGgY7cH9v4qUli5b3OGVVOzjAwY8h4Z2mSNH8kXjW2pz8ypzpiRuMEtFGBaWQWJz7w==} + engines: {node: '>=16'} + secure-json-parse@4.0.0: resolution: {integrity: sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==} @@ -20944,6 +20954,8 @@ snapshots: ajv-formats: 2.1.1(ajv@8.18.0) ajv-keywords: 5.1.0(ajv@8.18.0) + scimmy@1.3.5(patch_hash=775d80f86830b2c5dd1a250c9802c10f8fc3da3c7898373de5aa0c23993d1673): {} + secure-json-parse@4.0.0: {} selderee@0.11.0: From c247d4c1e33baec9772d4497a7b452dc16f2e91f Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Fri, 1 May 2026 14:56:39 +0100 Subject: [PATCH 16/63] feat(ee): PDF import (#2142) * feat: replace pdfjs-dist with firecrawl-pdf-inspector * use modified firecrawl-pdf-inspector * feat: pdf import * increase single file upload size limit * use npm package * sync * update package --- apps/client/src/ee/features.ts | 1 + .../page/components/page-import-modal.tsx | 30 +++- apps/server/package.json | 2 +- apps/server/src/common/features.ts | 1 + .../integrations/import/import.controller.ts | 5 +- .../import/services/import.service.ts | 51 +++++- pnpm-lock.yaml | 145 ++---------------- 7 files changed, 93 insertions(+), 142 deletions(-) diff --git a/apps/client/src/ee/features.ts b/apps/client/src/ee/features.ts index a9ab8b0d5..cacf851f2 100644 --- a/apps/client/src/ee/features.ts +++ b/apps/client/src/ee/features.ts @@ -8,6 +8,7 @@ export const Feature = { AI: 'ai', CONFLUENCE_IMPORT: 'import:confluence', DOCX_IMPORT: 'import:docx', + PDF_IMPORT: 'import:pdf', ATTACHMENT_INDEXING: 'attachment:indexing', SECURITY_SETTINGS: 'security:settings', MCP: 'mcp', diff --git a/apps/client/src/features/page/components/page-import-modal.tsx b/apps/client/src/features/page/components/page-import-modal.tsx index df6691d55..c1c12dc43 100644 --- a/apps/client/src/features/page/components/page-import-modal.tsx +++ b/apps/client/src/features/page/components/page-import-modal.tsx @@ -12,6 +12,7 @@ import { IconCheck, IconFileCode, IconFileTypeDocx, + IconFileTypePdf, IconFileTypeZip, IconMarkdown, IconX, @@ -90,12 +91,14 @@ function ImportFormatSelection({ spaceId, onClose }: ImportFormatSelection) { const markdownFileRef = useRef<() => void>(null); const htmlFileRef = useRef<() => void>(null); const docxFileRef = useRef<() => void>(null); + const pdfFileRef = useRef<() => void>(null); const notionFileRef = useRef<() => void>(null); const confluenceFileRef = useRef<() => void>(null); const zipFileRef = useRef<() => void>(null); const canUseConfluence = useHasFeature(Feature.CONFLUENCE_IMPORT); const canUseDocx = useHasFeature(Feature.DOCX_IMPORT); + const canUsePdf = useHasFeature(Feature.PDF_IMPORT); const upgradeLabel = useUpgradeLabel(); const handleZipUpload = async (selectedFile: File, source: string) => { @@ -244,7 +247,7 @@ function ImportFormatSelection({ spaceId, onClose }: ImportFormatSelection) { }, 3000); }, [fileTaskId]); - const maxSingleFileSize = bytes("20mb"); + const maxSingleFileSize = bytes("30mb"); const handleFileUpload = async (selectedFiles: File[]) => { if (!selectedFiles) { @@ -298,6 +301,7 @@ function ImportFormatSelection({ spaceId, onClose }: ImportFormatSelection) { if (markdownFileRef.current) markdownFileRef.current(); if (htmlFileRef.current) htmlFileRef.current(); if (docxFileRef.current) docxFileRef.current(); + if (pdfFileRef.current) pdfFileRef.current(); const pageCountText = pageCount === 1 ? `1 ${t("page")}` : `${pageCount} ${t("pages")}`; @@ -378,6 +382,30 @@ function ImportFormatSelection({ spaceId, onClose }: ImportFormatSelection) { )} + + {(props) => ( + + + + )} + + handleZipUpload(file, "notion")} accept="application/zip" diff --git a/apps/server/package.json b/apps/server/package.json index 794924876..c0eeddf33 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -37,6 +37,7 @@ "@aws-sdk/lib-storage": "3.1037.0", "@aws-sdk/s3-request-presigner": "3.1037.0", "@clickhouse/client": "^1.18.2", + "@docmost/pdf-inspector": "1.9.4", "@fastify/cookie": "^11.0.2", "@fastify/multipart": "^10.0.0", "@fastify/static": "^9.1.3", @@ -100,7 +101,6 @@ "p-limit": "^7.3.0", "passport-google-oauth20": "^2.0.0", "passport-jwt": "^4.0.1", - "pdfjs-dist": "^5.5.207", "pg-tsquery": "^8.4.2", "pgvector": "^0.2.1", "pino-http": "^11.0.0", diff --git a/apps/server/src/common/features.ts b/apps/server/src/common/features.ts index 38f226a86..c5fd9a200 100644 --- a/apps/server/src/common/features.ts +++ b/apps/server/src/common/features.ts @@ -8,6 +8,7 @@ export const Feature = { AI: 'ai', CONFLUENCE_IMPORT: 'import:confluence', DOCX_IMPORT: 'import:docx', + PDF_IMPORT: 'import:pdf', ATTACHMENT_INDEXING: 'attachment:indexing', SECURITY_SETTINGS: 'security:settings', MCP: 'mcp', diff --git a/apps/server/src/integrations/import/import.controller.ts b/apps/server/src/integrations/import/import.controller.ts index 7ee325e5f..cd2341ea5 100644 --- a/apps/server/src/integrations/import/import.controller.ts +++ b/apps/server/src/integrations/import/import.controller.ts @@ -51,9 +51,9 @@ export class ImportController { @AuthUser() user: User, @AuthWorkspace() workspace: Workspace, ) { - const validFileExtensions = ['.md', '.html', '.docx']; + const validFileExtensions = ['.md', '.html', '.docx', '.pdf']; - const maxFileSize = bytes('20mb'); + const maxFileSize = bytes('30mb'); let file = null; try { @@ -102,6 +102,7 @@ export class ImportController { '.md': 'markdown', '.html': 'html', '.docx': 'docx', + '.pdf': 'pdf', }; if (createdPage) { diff --git a/apps/server/src/integrations/import/services/import.service.ts b/apps/server/src/integrations/import/services/import.service.ts index 0eb3ae40d..1eb10ca80 100644 --- a/apps/server/src/integrations/import/services/import.service.ts +++ b/apps/server/src/integrations/import/services/import.service.ts @@ -63,7 +63,10 @@ export class ImportService { let createdPage = null; // For DOCX, we need the page ID upfront so images can reference it - const pageId = fileExtension === '.docx' ? uuid7() : undefined; + const pageId = + fileExtension === '.docx' || fileExtension === '.pdf' + ? uuid7() + : undefined; try { if (fileExtension.endsWith('.md')) { @@ -78,6 +81,14 @@ export class ImportService { pageId, userId, ); + } else if (fileExtension.endsWith('.pdf')) { + prosemirrorState = await this.processPdf( + fileBuffer, + workspaceId, + spaceId, + pageId, + userId, + ); } } catch (err) { const message = 'Error processing file content'; @@ -156,7 +167,7 @@ export class ImportService { let DocxImportModule: any; try { // eslint-disable-next-line @typescript-eslint/no-require-imports - DocxImportModule = require('./../../../ee/docx-import/docx-import.service'); + DocxImportModule = require('./../../../ee/document-import/docx-import.service'); } catch (err) { this.logger.error( 'DOCX import requested but EE module not bundled in this build', @@ -182,6 +193,42 @@ export class ImportService { return this.processHTML(html); } + async processPdf( + fileBuffer: Buffer, + workspaceId: string, + spaceId: string, + pageId: string, + userId: string, + ): Promise { + let PdfImportModule: any; + try { + // eslint-disable-next-line @typescript-eslint/no-require-imports + PdfImportModule = require('./../../../ee/document-import/pdf-import.service'); + } catch (err) { + this.logger.error( + 'PDF import requested but EE module not bundled in this build', + ); + throw new BadRequestException( + 'This feature requires a valid enterprise license.', + ); + } + + const pdfImportService = this.moduleRef.get( + PdfImportModule.PdfImportService, + { strict: false }, + ); + + const html = await pdfImportService.convertPdfToHtml( + fileBuffer, + workspaceId, + spaceId, + pageId, + userId, + ); + + return this.processHTML(html); + } + async createYdoc(prosemirrorJson: any): Promise { if (prosemirrorJson) { // this.logger.debug(`Converting prosemirror json state to ydoc`); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3985bc750..f6e1a7572 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -482,6 +482,9 @@ importers: '@clickhouse/client': specifier: ^1.18.2 version: 1.18.2 + '@docmost/pdf-inspector': + specifier: 1.9.4 + version: 1.9.4 '@fastify/cookie': specifier: ^11.0.2 version: 11.0.2 @@ -671,9 +674,6 @@ importers: passport-jwt: specifier: ^4.0.1 version: 4.0.1 - pdfjs-dist: - specifier: ^5.5.207 - version: 5.5.207 pg-tsquery: specifier: ^8.4.2 version: 8.4.2 @@ -1826,6 +1826,9 @@ packages: resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} engines: {node: '>=18'} + '@docmost/pdf-inspector@1.9.4': + resolution: {integrity: sha512-G5DNyDtLNxybTXWakqi7PuOEuSb/A2ZjDlv2WCkOkiHszPeILdrC+G0a4e4UP10yxvzuLfb23pJ5jy8fUSYZPw==} + '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -2762,76 +2765,6 @@ packages: cpu: [x64] os: [win32] - '@napi-rs/canvas-android-arm64@0.1.97': - resolution: {integrity: sha512-V1c/WVw+NzH8vk7ZK/O8/nyBSCQimU8sfMsB/9qeSvdkGKNU7+mxy/bIF0gTgeBFmHpj30S4E9WHMSrxXGQuVQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - - '@napi-rs/canvas-darwin-arm64@0.1.97': - resolution: {integrity: sha512-ok+SCEF4YejcxuJ9Rm+WWunHHpf2HmiPxfz6z1a/NFQECGXtsY7A4B8XocK1LmT1D7P174MzwPF9Wy3AUAwEPw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@napi-rs/canvas-darwin-x64@0.1.97': - resolution: {integrity: sha512-PUP6e6/UGlclUvAQNnuXCcnkpdUou6VYZfQOQxExLp86epOylmiwLkqXIvpFmjoTEDmPmXrI+coL/9EFU1gKPA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.97': - resolution: {integrity: sha512-XyXH2L/cic8eTNtbrXCcvqHtMX/nEOxN18+7rMrAM2XtLYC/EB5s0wnO1FsLMWmK+04ZSLN9FBGipo7kpIkcOw==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - - '@napi-rs/canvas-linux-arm64-gnu@0.1.97': - resolution: {integrity: sha512-Kuq/M3djq0K8ktgz6nPlK7Ne5d4uWeDxPpyKWOjWDK2RIOhHVtLtyLiJw2fuldw7Vn4mhw05EZXCEr4Q76rs9w==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@napi-rs/canvas-linux-arm64-musl@0.1.97': - resolution: {integrity: sha512-kKmSkQVnWeqg7qdsiXvYxKhAFuHz3tkBjW/zyQv5YKUPhotpaVhpBGv5LqCngzyuRV85SXoe+OFj+Tv0a0QXkQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@napi-rs/canvas-linux-riscv64-gnu@0.1.97': - resolution: {integrity: sha512-Jc7I3A51jnEOIAXeLsN/M/+Z28LUeakcsXs07FLq9prXc0eYOtVwsDEv913Gr+06IRo34gJJVgT0TXvmz+N2VA==} - engines: {node: '>= 10'} - cpu: [riscv64] - os: [linux] - - '@napi-rs/canvas-linux-x64-gnu@0.1.97': - resolution: {integrity: sha512-iDUBe7AilfuBSRbSa8/IGX38Mf+iCSBqoVKLSQ5XaY2JLOaqz1TVyPFEyIck7wT6mRQhQt5sN6ogfjIDfi74tg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@napi-rs/canvas-linux-x64-musl@0.1.97': - resolution: {integrity: sha512-AKLFd/v0Z5fvgqBDqhvqtAdx+fHMJ5t9JcUNKq4FIZ5WH+iegGm8HPdj00NFlCSnm83Fp3Ln8I2f7uq1aIiWaA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@napi-rs/canvas-win32-arm64-msvc@0.1.97': - resolution: {integrity: sha512-u883Yr6A6fO7Vpsy9YE4FVCIxzzo5sO+7pIUjjoDLjS3vQaNMkVzx5bdIpEL+ob+gU88WDK4VcxYMZ6nmnoX9A==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@napi-rs/canvas-win32-x64-msvc@0.1.97': - resolution: {integrity: sha512-sWtD2EE3fV0IzN+iiQUqr/Q1SwqWhs2O1FKItFlxtdDkikpEj5g7DKQpY3x55H/MAOnL8iomnlk3mcEeGiUMoQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@napi-rs/canvas@0.1.97': - resolution: {integrity: sha512-8cFniXvrIEnVwuNSRCW9wirRZbHvrD3JVujdS2P5n5xiJZNZMOZcfOvJ1pb66c7jXMKHHglJEDVJGbm8XWFcXQ==} - engines: {node: '>= 10'} - '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} @@ -8551,9 +8484,6 @@ packages: node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - node-readable-to-web-readable-stream@0.4.2: - resolution: {integrity: sha512-/cMZNI34v//jUTrI+UIo4ieHAB5EZRY/+7OmXZgBxaWBMcW2tGdceIw06RFxWxrKZ5Jp3sI2i5TsRo+CBhtVLQ==} - node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} @@ -8845,10 +8775,6 @@ packages: pause@0.0.1: resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==} - pdfjs-dist@5.5.207: - resolution: {integrity: sha512-WMqqw06w1vUt9ZfT0gOFhMf3wHsWhaCrxGrckGs5Cci6ybDW87IvPaOd2pnBwT6BJuP/CzXDZxjFgmSULLdsdw==} - engines: {node: '>=20.19.0 || >=22.13.0 || >=24'} - peberminta@0.9.0: resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==} @@ -10328,6 +10254,7 @@ packages: uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true uuid@11.1.0: @@ -12193,6 +12120,8 @@ snapshots: '@csstools/css-tokenizer@3.0.3': {} + '@docmost/pdf-inspector@1.9.4': {} + '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -13193,54 +13122,6 @@ snapshots: '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.2': optional: true - '@napi-rs/canvas-android-arm64@0.1.97': - optional: true - - '@napi-rs/canvas-darwin-arm64@0.1.97': - optional: true - - '@napi-rs/canvas-darwin-x64@0.1.97': - optional: true - - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.97': - optional: true - - '@napi-rs/canvas-linux-arm64-gnu@0.1.97': - optional: true - - '@napi-rs/canvas-linux-arm64-musl@0.1.97': - optional: true - - '@napi-rs/canvas-linux-riscv64-gnu@0.1.97': - optional: true - - '@napi-rs/canvas-linux-x64-gnu@0.1.97': - optional: true - - '@napi-rs/canvas-linux-x64-musl@0.1.97': - optional: true - - '@napi-rs/canvas-win32-arm64-msvc@0.1.97': - optional: true - - '@napi-rs/canvas-win32-x64-msvc@0.1.97': - optional: true - - '@napi-rs/canvas@0.1.97': - optionalDependencies: - '@napi-rs/canvas-android-arm64': 0.1.97 - '@napi-rs/canvas-darwin-arm64': 0.1.97 - '@napi-rs/canvas-darwin-x64': 0.1.97 - '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.97 - '@napi-rs/canvas-linux-arm64-gnu': 0.1.97 - '@napi-rs/canvas-linux-arm64-musl': 0.1.97 - '@napi-rs/canvas-linux-riscv64-gnu': 0.1.97 - '@napi-rs/canvas-linux-x64-gnu': 0.1.97 - '@napi-rs/canvas-linux-x64-musl': 0.1.97 - '@napi-rs/canvas-win32-arm64-msvc': 0.1.97 - '@napi-rs/canvas-win32-x64-msvc': 0.1.97 - optional: true - '@napi-rs/wasm-runtime@0.2.12': dependencies: '@emnapi/core': 1.8.1 @@ -19627,9 +19508,6 @@ snapshots: node-int64@0.4.0: {} - node-readable-to-web-readable-stream@0.4.2: - optional: true - node-releases@2.0.27: {} nodemailer@8.0.5: {} @@ -19981,11 +19859,6 @@ snapshots: pause@0.0.1: {} - pdfjs-dist@5.5.207: - optionalDependencies: - '@napi-rs/canvas': 0.1.97 - node-readable-to-web-readable-stream: 0.4.2 - peberminta@0.9.0: {} pend@1.2.0: {} From b74ca00bfd121211c0e15240235f038ab15387f8 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Fri, 1 May 2026 14:57:32 +0100 Subject: [PATCH 17/63] sync --- apps/server/src/ee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/ee b/apps/server/src/ee index 109829076..211783940 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit 109829076c8d81f6d77836820a5caa63ae8d073f +Subproject commit 211783940cae7f6809eadace1c232f1db5c9fc80 From 17f3158a3b09adf1978aecdefb15679c05645744 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Fri, 1 May 2026 20:00:20 +0100 Subject: [PATCH 18/63] update aws packages --- apps/server/package.json | 6 +- pnpm-lock.yaml | 279 ++++++++++++++++++++------------------- 2 files changed, 143 insertions(+), 142 deletions(-) diff --git a/apps/server/package.json b/apps/server/package.json index c0eeddf33..f9cbdc04a 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -33,9 +33,9 @@ "@ai-sdk/google": "^3.0.52", "@ai-sdk/openai": "^3.0.47", "@ai-sdk/openai-compatible": "^2.0.37", - "@aws-sdk/client-s3": "3.1037.0", - "@aws-sdk/lib-storage": "3.1037.0", - "@aws-sdk/s3-request-presigner": "3.1037.0", + "@aws-sdk/client-s3": "3.1040.0", + "@aws-sdk/lib-storage": "3.1040.0", + "@aws-sdk/s3-request-presigner": "3.1040.0", "@clickhouse/client": "^1.18.2", "@docmost/pdf-inspector": "1.9.4", "@fastify/cookie": "^11.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f6e1a7572..a3ca7b679 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -471,14 +471,14 @@ importers: specifier: ^2.0.37 version: 2.0.37(zod@4.3.6) '@aws-sdk/client-s3': - specifier: 3.1037.0 - version: 3.1037.0 + specifier: 3.1040.0 + version: 3.1040.0 '@aws-sdk/lib-storage': - specifier: 3.1037.0 - version: 3.1037.0(@aws-sdk/client-s3@3.1037.0) + specifier: 3.1040.0 + version: 3.1040.0(@aws-sdk/client-s3@3.1040.0) '@aws-sdk/s3-request-presigner': - specifier: 3.1037.0 - version: 3.1037.0 + specifier: 3.1040.0 + version: 3.1040.0 '@clickhouse/client': specifier: ^1.18.2 version: 1.18.2 @@ -941,55 +941,55 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-s3@3.1037.0': - resolution: {integrity: sha512-DBmA1jAW8ST6C4srBxeL1/RLIir/d8WOm4s4mi59mGp6mBktHM59Kwb7GuURaCO60cotuce5zr0sKpMLPcBQyA==} + '@aws-sdk/client-s3@3.1040.0': + resolution: {integrity: sha512-Ldfby1xDrlZwNY2NxP9pwdVrf8sqHbGBKP1UkoG/oWcePGlGhjY8iVwy8hRy9f1EQfHVFWIFunwHaPQxhYTnWQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/core@3.974.5': - resolution: {integrity: sha512-lMPlYlYfQdNZhlkJgnkmESwrY+hNh3PljmZ+37oAqLNdJ6rnILAwFSyc6B3bJeDOtMORNnMQIej0aTRuOlDyhQ==} + '@aws-sdk/core@3.974.7': + resolution: {integrity: sha512-YhRC90ofz5oolTJZlA8voU/oUrCB2azi8Usx51k8hhB5LpWbYQMMXKUqSqkoL0Cru+RQJgWTHpAfEDDIwfUhJw==} engines: {node: '>=20.0.0'} '@aws-sdk/crc64-nvme@3.972.7': resolution: {integrity: sha512-QUagVVBbC8gODCF6e1aV0mE2TXWB9Opz4k8EJFdNrujUVQm5R4AjJa1mpOqzwOuROBzqJU9zawzig7M96L8Ejg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.31': - resolution: {integrity: sha512-X/yGB73LmDW/6MdDJGCDzZBUXnM3ys4vs9l+5ZTJmiEswDdP1OjeoAFlFjVGS9o4KB2wZWQ9KOfdVNSSK6Ep3w==} + '@aws-sdk/credential-provider-env@3.972.33': + resolution: {integrity: sha512-bJV7eViSJV6GSuuN+VIdNVPdwPsNSf75BiC2v5alPrjR/OCcqgKwSZInKbDFz9mNeizldsyf67jt6YSIiv53Cw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.33': - resolution: {integrity: sha512-c0ZF+lwoWVvX5iCaGKL5T/4DnIw88CGqxA0BcBs3U86mIp5EZYPVg+KSPkMXOyokmADvNewiMUfSG2uFwjRp0g==} + '@aws-sdk/credential-provider-http@3.972.35': + resolution: {integrity: sha512-x/BQGEIdq0oI+4WxLjKmnQvT7CnF9r8ezdGt7wXwxb7ckHXQz0Zmgxt8v3Ne0JaT3R5YefmuybHX6E8EnsDXyA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.972.35': - resolution: {integrity: sha512-jsU4u/cRkKFLKQS0k918FQ27fzXLG5ENiLWQMYE6581zLeI2hWh04ptlrvZMB3wJT/5d+vSzJk74X1CMFr4y8Q==} + '@aws-sdk/credential-provider-ini@3.972.37': + resolution: {integrity: sha512-eUTpmWfd/BKsq9medhCRcu+GRAhFP2Zrn7/2jKDHHOOjCkhrMoTp/t4cEthqFoG7gE0VGp5wUxrXTdvBCmSmJg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.35': - resolution: {integrity: sha512-5oa3j0cA50jPqgNhZ9XdJVopuzUf1klRb28/2MfLYWWiPi9DRVvbrBWT+DidbHTT36520VuXZJahQwR+YgSjrg==} + '@aws-sdk/credential-provider-login@3.972.37': + resolution: {integrity: sha512-Ty68y8ISSC+g5Q3D0K8uAaoINwvfaOslnNpsF/LgVUxyosYXHawcK2yV4HLXDVugiTTYLQfJfcw0ce5meAGkKw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.36': - resolution: {integrity: sha512-4nT2T8Z7vH8KE9EdjEsuIlHpZSlcaK2PrKbQBjuUGU46BCCzF3WvP0u0Uiosni3Ykmmn4rWLVawoOCLotUtCbg==} + '@aws-sdk/credential-provider-node@3.972.38': + resolution: {integrity: sha512-BQ9XYnBDVxR2HuV5huXYQYF/PZMTsY+EnwfGnCU2cA8Zw63XpkOtPY8WqiMIZMQCrKPQQEiFURS/o9CIolRLqg==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.31': - resolution: {integrity: sha512-eKeT4MXumpBJsrDLCYcSzIkFPVTFn/es7It2oogp2OhU/ic7P/+xzFpQx9ZhwtXS57Mc5S42BPWi7lHmvs/nYg==} + '@aws-sdk/credential-provider-process@3.972.33': + resolution: {integrity: sha512-yfjGksI9WQbdMObb0VeLXqzTLI+a0qXLJT9gCDiv0+X/xjPpI3mTz6a5FibrhpuEKIe0gSgvs3MaoFZy5cx4WA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.35': - resolution: {integrity: sha512-bCuBdfnj0KGDMdLp6utMTLiJcFN2ek9EgZinxQZZSc3FxjJ/HSqeqab2cjbnoNfy8RM6suDCsRkmVY1izp9I+A==} + '@aws-sdk/credential-provider-sso@3.972.37': + resolution: {integrity: sha512-fpwE+20ntpp3i9Xb9vUuQfXLDKYHH+5I2V+ZG96SX1nBzrruhy10RXDgmN7t1etOz3c55stlA3TeQASUA451NQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.35': - resolution: {integrity: sha512-swW6Bwvl8lanyEMtZOWE/oR6yqcRQH4HTQZUVsnDVgoXvRjRywpYpLv2BWwjUFyjPrqsdX6FeTkf4tMSe/qFTQ==} + '@aws-sdk/credential-provider-web-identity@3.972.37': + resolution: {integrity: sha512-aryawqyebf+3WhAFNHfF62rekFpYtVcVN7dQ89qnAWsa4n5hJst8qBG6gXC24WHtW7Nnhkf9ScYnjwo0Brn3bw==} engines: {node: '>=20.0.0'} - '@aws-sdk/lib-storage@3.1037.0': - resolution: {integrity: sha512-ZFg5Vf4RKS48xTm7DfXTeR0Rvn/Fcu6YFdRygGnvhA+gW3W0WtsRqM1CzkWevYBztdUUAsZqtGbMj9Eu0OaeEg==} + '@aws-sdk/lib-storage@3.1040.0': + resolution: {integrity: sha512-4cPpxs/2Gnzm7dKn2EBTPf0/rPNM5BoOleWSNn03QPGkELPDg9VmVwUhXZsDcb8k8F9wm5ft9n7BSNXKAjoIWw==} engines: {node: '>=20.0.0'} peerDependencies: - '@aws-sdk/client-s3': ^3.1037.0 + '@aws-sdk/client-s3': ^3.1040.0 '@aws-sdk/middleware-bucket-endpoint@3.972.10': resolution: {integrity: sha512-Vbc2frZH7wXlMNd+ZZSXUEs/l1Sv8Jj4zUnIfwrYF5lwaLdXHZ9xx4U3rjUcaye3HRhFVc+E5DbBxpRAbB16BA==} @@ -999,8 +999,8 @@ packages: resolution: {integrity: sha512-2Yn0f1Qiq/DjxYR3wfI3LokXnjOhFM7Ssn4LTdFDIxRMCE6I32MAsVnhPX1cUZsuVA9tiZtwwhlSLAtFGxAZlQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.974.13': - resolution: {integrity: sha512-b6QUe2hQX9XsnCzp6mtzVaERhganDKeb8lmGL6pVhr7rRVH9S9keDFW7uKytuuqmcY5943FixoGqn/QL+sbUBA==} + '@aws-sdk/middleware-flexible-checksums@3.974.15': + resolution: {integrity: sha512-j4Zp7rA1HfhDTteICnx/tPax4N/v5wmytgguXExUGyEwQ8Ug4EBA4kjp9puFAN1UZoBVpxoiXMiuTFvjaHjeEw==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-host-header@3.972.10': @@ -1019,36 +1019,36 @@ packages: resolution: {integrity: sha512-+zz6f79Kj9V5qFK2P+D8Ehjnw4AhphAlCAsPjUqEcInA9umtSSKMrHbSagEeOIsDNuvVrH98bjRHcyQukTrhaQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.34': - resolution: {integrity: sha512-/UL96JKjsjdodcRRMKl99tLQvK6Oi9ptLC9iU1yiTF/ruaDX0mtBBtnLNZDxIZRJOCVOtB49ed1YaTadqygk8Q==} + '@aws-sdk/middleware-sdk-s3@3.972.36': + resolution: {integrity: sha512-YhPix+0x/MdQrb1Ug1GDKeS5fqylIy+naz800asX8II4jqfTk2KY2KhmmYCwZcky8YWtRQQwWCGdoqeAnip8Uw==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-ssec@3.972.10': resolution: {integrity: sha512-Gli9A0u8EVVb+5bFDGS/QbSVg28w/wpEidg1ggVcSj65BDTdGR6punsOcVjqdiu1i42WHWo51MCvARPIIz9juw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-user-agent@3.972.35': - resolution: {integrity: sha512-hOFWNOjVmOocpRlrU04nYxjMOeoe0Obu5AXEuhB8zblMCPl3cG1hdluQCZERRKFyhMQjwZnDbhSHjoMUjetFGw==} + '@aws-sdk/middleware-user-agent@3.972.37': + resolution: {integrity: sha512-N1oNpdiLoVAWYD3WFBnUi3LlfoDA06ZHo4ozyjbsJNLvILzvt//0CnR8N+CZ0NWeYgVB/5V59ivixHCWCx2ALw==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.997.3': - resolution: {integrity: sha512-SivE6GP228IVgfsrr2c/vqTg95X0Qj39Yw4uIrcddpkUzIltNMoNOR62leHOLhODfjv9K8X2mPTwS69A5kT0nQ==} + '@aws-sdk/nested-clients@3.997.5': + resolution: {integrity: sha512-jGFr6DxtcMTmzOkG/a0jCZYv4BBDmeNYVeO+/memSoDkYCJu4Y58xviYmzwJfYyIVSts+X/BVjJm1uGBnwHEMg==} engines: {node: '>=20.0.0'} '@aws-sdk/region-config-resolver@3.972.13': resolution: {integrity: sha512-CvJ2ZIjK/jVD/lbOpowBVElJyC1YxLTIJ13yM0AEo0t2v7swOzGjSA6lJGH+DwZXQhcjUjoYwc8bVYCX5MDr1A==} engines: {node: '>=20.0.0'} - '@aws-sdk/s3-request-presigner@3.1037.0': - resolution: {integrity: sha512-rZQS8DxrqPYXzOvaoysf6L4fHmgFbndZz3GfUMhlHG1iWmcQqH7v0AGhpjyNBY3cYAX8+CAkOkD4VUrntnHNbQ==} + '@aws-sdk/s3-request-presigner@3.1040.0': + resolution: {integrity: sha512-AmesZGG/B5sDIiWahyY11fOkXSsuHc7LciE88YFURehMVSdEORo2Vzz1d2kBgmJG9oar5Vmmwf9X/w7mqb7ytg==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.996.22': - resolution: {integrity: sha512-/rXhMXteD+BqhFd0nYprAgcZ/KtU+963uftPqd3tiFcFfooHZINXUGtOmo2SQjRVauCTNqIEzkwuSETdZFqTTA==} + '@aws-sdk/signature-v4-multi-region@3.996.24': + resolution: {integrity: sha512-amP7tLikppN940wbBFISYqiuzVmpzMS9U3mcgtmVLjX4fdWI/SNCvrXv6ZxfVzTT4cT0rPKOLhFah2xLwzREWw==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1036.0': - resolution: {integrity: sha512-aNSJ6jjDYayxN9ZA1JpycVScX93Lx03kKZ1EXt3DGOTahcWVLJj3oLAlop0xKP+vP2Ga2t49p1tEaMkTbCCaZA==} + '@aws-sdk/token-providers@3.1039.0': + resolution: {integrity: sha512-NMSFL2HwkAOoCeLCQiqoOq5pT3vVbSjww2QZTuYgYknVwhhv125PSDzZIcL5EYnlxuPWjEOdauZK+FspkZDVdw==} engines: {node: '>=20.0.0'} '@aws-sdk/types@3.973.8': @@ -1074,8 +1074,8 @@ packages: '@aws-sdk/util-user-agent-browser@3.972.10': resolution: {integrity: sha512-FAzqXvfEssGdSIz8ejatan0bOdx1qefBWKF/gWmVBXIP1HkS7v/wjjaqrAGGKvyihrXTXW00/2/1nTJtxpXz7g==} - '@aws-sdk/util-user-agent-node@3.973.21': - resolution: {integrity: sha512-Av4UHTcAWgdvbN0IP9pbtf4Qa1+6LtJqQdZWj5pLn5J67w0pnJJAZZ+7JPPcj2KN3378zD2JDM9DwJKEyvyMTQ==} + '@aws-sdk/util-user-agent-node@3.973.23': + resolution: {integrity: sha512-gGwq8L2Euw0aNG6Ey4EktiAo3fSCVoDy1CaBIthd+oeaKHPXUrNaApMewQ6La5Hv0lcznOtECZaNvYyc5LXXfA==} engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -1083,8 +1083,8 @@ packages: aws-crt: optional: true - '@aws-sdk/xml-builder@3.972.19': - resolution: {integrity: sha512-Cw8IOMdBUEIl8ZlhRC3Dc/E64D5B5/8JhV6vhPLiPfJwcRC84S6F8aBOIi/N4vR9ZyA4I5Cc0Ateb/9EHaJXeQ==} + '@aws-sdk/xml-builder@3.972.22': + resolution: {integrity: sha512-PMYKKtJd70IsSG0yHrdAbxBr+ZWBKLvzFZfD3/urxgf6hXVMzuU5M+3MJ5G67RpOmLBu1fAUN65SbWuKUCOlAA==} engines: {node: '>=20.0.0'} '@aws/lambda-invoke-store@0.2.3': @@ -3915,7 +3915,7 @@ packages: resolution: {integrity: sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==} '@react-email/body@0.3.0': - resolution: {integrity: sha512-uGo0BOOzjbMUo3lu+BIDWayvn5o6Xyfmnlla5VGf05n8gHMvO1ll7U4FtzWe3hxMLwt53pmc4iE0M+B5slG+Ug==} + resolution: {integrity: sha512-uGo0BOOzjbMUo3lu+BIDWayvn5o6Xyfmnlla5VGf05n8gHMvO1ll7U4FtzWe3hxMLxMLwt53pmc4iE0M+B5slG+Ug==} engines: {node: '>=20.0.0'} peerDependencies: react: ^18.0 || ^19.0 || ^19.0.0-rc @@ -4281,8 +4281,8 @@ packages: resolution: {integrity: sha512-ZZkgyjnJppiZbIm6Qbx92pbXYi1uzenIvGhBSCDlc7NwuAkiqSgS75j1czAD25ZLs2FjMjYy1q7gyRVWG6JA0Q==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.5.5': - resolution: {integrity: sha512-wnYOpB5vATFKWrY2Z9Alb0KhjZI6AbzU6Fbz3Hq2GnURdRYWB4q+qWivQtSTwXcmWUA3MZ6krfwL6Cq5MAbxsA==} + '@smithy/middleware-retry@4.5.7': + resolution: {integrity: sha512-bRt6ZImqVSeTk39Nm81K20ObIiAZ3WefY7G6+iz/0tZjs4dgRRjvRX2sgsH+zi6iDCRR/aQvQofLKxxz4rPBZg==} engines: {node: '>=18.0.0'} '@smithy/middleware-serde@4.2.20': @@ -4317,8 +4317,8 @@ packages: resolution: {integrity: sha512-hr+YyqBD23GVvRxGGrcc/oOeNlK3PzT5Fu4dzrDXxzS1LpFiuL2PQQqKPs87M79aW7ziMs+nvB3qdw77SqE7Lw==} engines: {node: '>=18.0.0'} - '@smithy/service-error-classification@4.3.0': - resolution: {integrity: sha512-9jKsBYQRPR0xBLgc2415RsA5PIcP2sis4oBdN9s0D13cg1B1284mNTjx9Yc+BEERXzuPm5ObktI96OxsKh8E9A==} + '@smithy/service-error-classification@4.3.1': + resolution: {integrity: sha512-aUQuDGh760ts/8MU+APjIZhlLPKhIIfqyzZaJikLEIMrdxFvxuLYD0WxWzaYWpmLbQlXDe9p7EWM3HsBe0K6Gw==} engines: {node: '>=18.0.0'} '@smithy/shared-ini-file-loader@4.4.9': @@ -4385,8 +4385,8 @@ packages: resolution: {integrity: sha512-1Su2vj9RYNDEv/V+2E+jXkkwGsgR7dc4sfHn9Z7ruzQHJIEni9zzw5CauvRXlFJfmgcqYP8fWa0dkh2Q2YaQyw==} engines: {node: '>=18.0.0'} - '@smithy/util-retry@4.3.4': - resolution: {integrity: sha512-FY1UQQ1VFmMwiYp1GVS4MeaGD5O0blLNYK0xCRHU+mJgeoH/hSY8Ld8sJWKQ6uznkh14HveRGQJncgPyNl9J+A==} + '@smithy/util-retry@4.3.6': + resolution: {integrity: sha512-p6/FO1n2KxMeQyna067i0uJ6TSbb165ZhnRtCpWh4Foxqbfc6oW+XITaL8QkFJj3KFnDe2URt4gOhgU06EP9ew==} engines: {node: '>=18.0.0'} '@smithy/util-stream@4.5.25': @@ -4405,8 +4405,8 @@ packages: resolution: {integrity: sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==} engines: {node: '>=18.0.0'} - '@smithy/util-waiter@4.2.16': - resolution: {integrity: sha512-GtclrKoZ3Lt7jPQ7aTIYKfjY92OgceScftVnkTsG8e1KV8rkvZgN+ny6YSRhd9hxB8rZtwVbmln7NTvE5O3GmQ==} + '@smithy/util-waiter@4.3.0': + resolution: {integrity: sha512-JyjYmLAfS+pdxF92o4yLgEoy0zhayKTw73FU1aofLWwLcJw7iSqIY2exGmMTrl/lmZugP5p/zxdFSippJDfKWA==} engines: {node: '>=18.0.0'} '@smithy/uuid@1.1.2': @@ -6862,8 +6862,8 @@ packages: fast-xml-builder@1.1.5: resolution: {integrity: sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==} - fast-xml-parser@5.7.1: - resolution: {integrity: sha512-8Cc3f8GUGUULg34pBch/KGyPLglS+OFs05deyOlY7fL2MTagYPKrVQNmR1fLF/yJ9PH5ZSTd3YDF6pnmeZU+zA==} + fast-xml-parser@5.7.2: + resolution: {integrity: sha512-P7oW7tLbYnhOLQk/Gv7cZgzgMPP/XN03K02/Jy6Y/NHzyIAIpxuZIM/YqAkfiXFPxA2CTm7NtCijK9EDu09u2w==} hasBin: true fastify-ip@2.0.0: @@ -10814,29 +10814,29 @@ snapshots: '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-s3@3.1037.0': + '@aws-sdk/client-s3@3.1040.0': dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.5 - '@aws-sdk/credential-provider-node': 3.972.36 + '@aws-sdk/core': 3.974.7 + '@aws-sdk/credential-provider-node': 3.972.38 '@aws-sdk/middleware-bucket-endpoint': 3.972.10 '@aws-sdk/middleware-expect-continue': 3.972.10 - '@aws-sdk/middleware-flexible-checksums': 3.974.13 + '@aws-sdk/middleware-flexible-checksums': 3.974.15 '@aws-sdk/middleware-host-header': 3.972.10 '@aws-sdk/middleware-location-constraint': 3.972.10 '@aws-sdk/middleware-logger': 3.972.10 '@aws-sdk/middleware-recursion-detection': 3.972.11 - '@aws-sdk/middleware-sdk-s3': 3.972.34 + '@aws-sdk/middleware-sdk-s3': 3.972.36 '@aws-sdk/middleware-ssec': 3.972.10 - '@aws-sdk/middleware-user-agent': 3.972.35 + '@aws-sdk/middleware-user-agent': 3.972.37 '@aws-sdk/region-config-resolver': 3.972.13 - '@aws-sdk/signature-v4-multi-region': 3.996.22 + '@aws-sdk/signature-v4-multi-region': 3.996.24 '@aws-sdk/types': 3.973.8 '@aws-sdk/util-endpoints': 3.996.8 '@aws-sdk/util-user-agent-browser': 3.972.10 - '@aws-sdk/util-user-agent-node': 3.973.21 + '@aws-sdk/util-user-agent-node': 3.973.23 '@smithy/config-resolver': 4.4.17 '@smithy/core': 3.23.17 '@smithy/eventstream-serde-browser': 4.2.14 @@ -10850,7 +10850,7 @@ snapshots: '@smithy/md5-js': 4.2.14 '@smithy/middleware-content-length': 4.2.14 '@smithy/middleware-endpoint': 4.4.32 - '@smithy/middleware-retry': 4.5.5 + '@smithy/middleware-retry': 4.5.7 '@smithy/middleware-serde': 4.2.20 '@smithy/middleware-stack': 4.2.14 '@smithy/node-config-provider': 4.3.14 @@ -10866,18 +10866,18 @@ snapshots: '@smithy/util-defaults-mode-node': 4.2.54 '@smithy/util-endpoints': 3.4.2 '@smithy/util-middleware': 4.2.14 - '@smithy/util-retry': 4.3.4 + '@smithy/util-retry': 4.3.6 '@smithy/util-stream': 4.5.25 '@smithy/util-utf8': 4.2.2 - '@smithy/util-waiter': 4.2.16 + '@smithy/util-waiter': 4.3.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.974.5': + '@aws-sdk/core@3.974.7': dependencies: '@aws-sdk/types': 3.973.8 - '@aws-sdk/xml-builder': 3.972.19 + '@aws-sdk/xml-builder': 3.972.22 '@smithy/core': 3.23.17 '@smithy/node-config-provider': 4.3.14 '@smithy/property-provider': 4.2.14 @@ -10887,7 +10887,7 @@ snapshots: '@smithy/types': 4.14.1 '@smithy/util-base64': 4.3.2 '@smithy/util-middleware': 4.2.14 - '@smithy/util-retry': 4.3.4 + '@smithy/util-retry': 4.3.6 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 @@ -10896,17 +10896,17 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.31': + '@aws-sdk/credential-provider-env@3.972.33': dependencies: - '@aws-sdk/core': 3.974.5 + '@aws-sdk/core': 3.974.7 '@aws-sdk/types': 3.973.8 '@smithy/property-provider': 4.2.14 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.33': + '@aws-sdk/credential-provider-http@3.972.35': dependencies: - '@aws-sdk/core': 3.974.5 + '@aws-sdk/core': 3.974.7 '@aws-sdk/types': 3.973.8 '@smithy/fetch-http-handler': 5.3.17 '@smithy/node-http-handler': 4.6.1 @@ -10917,16 +10917,16 @@ snapshots: '@smithy/util-stream': 4.5.25 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.972.35': + '@aws-sdk/credential-provider-ini@3.972.37': dependencies: - '@aws-sdk/core': 3.974.5 - '@aws-sdk/credential-provider-env': 3.972.31 - '@aws-sdk/credential-provider-http': 3.972.33 - '@aws-sdk/credential-provider-login': 3.972.35 - '@aws-sdk/credential-provider-process': 3.972.31 - '@aws-sdk/credential-provider-sso': 3.972.35 - '@aws-sdk/credential-provider-web-identity': 3.972.35 - '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/core': 3.974.7 + '@aws-sdk/credential-provider-env': 3.972.33 + '@aws-sdk/credential-provider-http': 3.972.35 + '@aws-sdk/credential-provider-login': 3.972.37 + '@aws-sdk/credential-provider-process': 3.972.33 + '@aws-sdk/credential-provider-sso': 3.972.37 + '@aws-sdk/credential-provider-web-identity': 3.972.37 + '@aws-sdk/nested-clients': 3.997.5 '@aws-sdk/types': 3.973.8 '@smithy/credential-provider-imds': 4.2.14 '@smithy/property-provider': 4.2.14 @@ -10936,10 +10936,10 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.972.35': + '@aws-sdk/credential-provider-login@3.972.37': dependencies: - '@aws-sdk/core': 3.974.5 - '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/core': 3.974.7 + '@aws-sdk/nested-clients': 3.997.5 '@aws-sdk/types': 3.973.8 '@smithy/property-provider': 4.2.14 '@smithy/protocol-http': 5.3.14 @@ -10949,14 +10949,14 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.972.36': + '@aws-sdk/credential-provider-node@3.972.38': dependencies: - '@aws-sdk/credential-provider-env': 3.972.31 - '@aws-sdk/credential-provider-http': 3.972.33 - '@aws-sdk/credential-provider-ini': 3.972.35 - '@aws-sdk/credential-provider-process': 3.972.31 - '@aws-sdk/credential-provider-sso': 3.972.35 - '@aws-sdk/credential-provider-web-identity': 3.972.35 + '@aws-sdk/credential-provider-env': 3.972.33 + '@aws-sdk/credential-provider-http': 3.972.35 + '@aws-sdk/credential-provider-ini': 3.972.37 + '@aws-sdk/credential-provider-process': 3.972.33 + '@aws-sdk/credential-provider-sso': 3.972.37 + '@aws-sdk/credential-provider-web-identity': 3.972.37 '@aws-sdk/types': 3.973.8 '@smithy/credential-provider-imds': 4.2.14 '@smithy/property-provider': 4.2.14 @@ -10966,20 +10966,20 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.972.31': + '@aws-sdk/credential-provider-process@3.972.33': dependencies: - '@aws-sdk/core': 3.974.5 + '@aws-sdk/core': 3.974.7 '@aws-sdk/types': 3.973.8 '@smithy/property-provider': 4.2.14 '@smithy/shared-ini-file-loader': 4.4.9 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.972.35': + '@aws-sdk/credential-provider-sso@3.972.37': dependencies: - '@aws-sdk/core': 3.974.5 - '@aws-sdk/nested-clients': 3.997.3 - '@aws-sdk/token-providers': 3.1036.0 + '@aws-sdk/core': 3.974.7 + '@aws-sdk/nested-clients': 3.997.5 + '@aws-sdk/token-providers': 3.1039.0 '@aws-sdk/types': 3.973.8 '@smithy/property-provider': 4.2.14 '@smithy/shared-ini-file-loader': 4.4.9 @@ -10988,10 +10988,10 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.972.35': + '@aws-sdk/credential-provider-web-identity@3.972.37': dependencies: - '@aws-sdk/core': 3.974.5 - '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/core': 3.974.7 + '@aws-sdk/nested-clients': 3.997.5 '@aws-sdk/types': 3.973.8 '@smithy/property-provider': 4.2.14 '@smithy/shared-ini-file-loader': 4.4.9 @@ -11000,9 +11000,9 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/lib-storage@3.1037.0(@aws-sdk/client-s3@3.1037.0)': + '@aws-sdk/lib-storage@3.1040.0(@aws-sdk/client-s3@3.1040.0)': dependencies: - '@aws-sdk/client-s3': 3.1037.0 + '@aws-sdk/client-s3': 3.1040.0 '@smithy/middleware-endpoint': 4.4.32 '@smithy/protocol-http': 5.3.14 '@smithy/smithy-client': 4.12.13 @@ -11029,12 +11029,12 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.974.13': + '@aws-sdk/middleware-flexible-checksums@3.974.15': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.974.5 + '@aws-sdk/core': 3.974.7 '@aws-sdk/crc64-nvme': 3.972.7 '@aws-sdk/types': 3.973.8 '@smithy/is-array-buffer': 4.2.2 @@ -11073,9 +11073,9 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.34': + '@aws-sdk/middleware-sdk-s3@3.972.36': dependencies: - '@aws-sdk/core': 3.974.5 + '@aws-sdk/core': 3.974.7 '@aws-sdk/types': 3.973.8 '@aws-sdk/util-arn-parser': 3.972.3 '@smithy/core': 3.23.17 @@ -11096,32 +11096,32 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.972.35': + '@aws-sdk/middleware-user-agent@3.972.37': dependencies: - '@aws-sdk/core': 3.974.5 + '@aws-sdk/core': 3.974.7 '@aws-sdk/types': 3.973.8 '@aws-sdk/util-endpoints': 3.996.8 '@smithy/core': 3.23.17 '@smithy/protocol-http': 5.3.14 '@smithy/types': 4.14.1 - '@smithy/util-retry': 4.3.4 + '@smithy/util-retry': 4.3.6 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.3': + '@aws-sdk/nested-clients@3.997.5': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.5 + '@aws-sdk/core': 3.974.7 '@aws-sdk/middleware-host-header': 3.972.10 '@aws-sdk/middleware-logger': 3.972.10 '@aws-sdk/middleware-recursion-detection': 3.972.11 - '@aws-sdk/middleware-user-agent': 3.972.35 + '@aws-sdk/middleware-user-agent': 3.972.37 '@aws-sdk/region-config-resolver': 3.972.13 - '@aws-sdk/signature-v4-multi-region': 3.996.22 + '@aws-sdk/signature-v4-multi-region': 3.996.24 '@aws-sdk/types': 3.973.8 '@aws-sdk/util-endpoints': 3.996.8 '@aws-sdk/util-user-agent-browser': 3.972.10 - '@aws-sdk/util-user-agent-node': 3.973.21 + '@aws-sdk/util-user-agent-node': 3.973.23 '@smithy/config-resolver': 4.4.17 '@smithy/core': 3.23.17 '@smithy/fetch-http-handler': 5.3.17 @@ -11129,7 +11129,7 @@ snapshots: '@smithy/invalid-dependency': 4.2.14 '@smithy/middleware-content-length': 4.2.14 '@smithy/middleware-endpoint': 4.4.32 - '@smithy/middleware-retry': 4.5.5 + '@smithy/middleware-retry': 4.5.7 '@smithy/middleware-serde': 4.2.20 '@smithy/middleware-stack': 4.2.14 '@smithy/node-config-provider': 4.3.14 @@ -11145,7 +11145,7 @@ snapshots: '@smithy/util-defaults-mode-node': 4.2.54 '@smithy/util-endpoints': 3.4.2 '@smithy/util-middleware': 4.2.14 - '@smithy/util-retry': 4.3.4 + '@smithy/util-retry': 4.3.6 '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 transitivePeerDependencies: @@ -11159,9 +11159,9 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/s3-request-presigner@3.1037.0': + '@aws-sdk/s3-request-presigner@3.1040.0': dependencies: - '@aws-sdk/signature-v4-multi-region': 3.996.22 + '@aws-sdk/signature-v4-multi-region': 3.996.24 '@aws-sdk/types': 3.973.8 '@aws-sdk/util-format-url': 3.972.10 '@smithy/middleware-endpoint': 4.4.32 @@ -11170,19 +11170,19 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.996.22': + '@aws-sdk/signature-v4-multi-region@3.996.24': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.972.34 + '@aws-sdk/middleware-sdk-s3': 3.972.36 '@aws-sdk/types': 3.973.8 '@smithy/protocol-http': 5.3.14 '@smithy/signature-v4': 5.3.14 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1036.0': + '@aws-sdk/token-providers@3.1039.0': dependencies: - '@aws-sdk/core': 3.974.5 - '@aws-sdk/nested-clients': 3.997.3 + '@aws-sdk/core': 3.974.7 + '@aws-sdk/nested-clients': 3.997.5 '@aws-sdk/types': 3.973.8 '@smithy/property-provider': 4.2.14 '@smithy/shared-ini-file-loader': 4.4.9 @@ -11226,19 +11226,20 @@ snapshots: bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.973.21': + '@aws-sdk/util-user-agent-node@3.973.23': dependencies: - '@aws-sdk/middleware-user-agent': 3.972.35 + '@aws-sdk/middleware-user-agent': 3.972.37 '@aws-sdk/types': 3.973.8 '@smithy/node-config-provider': 4.3.14 '@smithy/types': 4.14.1 '@smithy/util-config-provider': 4.2.2 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.19': + '@aws-sdk/xml-builder@3.972.22': dependencies: + '@nodable/entities': 2.1.0 '@smithy/types': 4.14.1 - fast-xml-parser: 5.7.1 + fast-xml-parser: 5.7.2 tslib: 2.8.1 '@aws/lambda-invoke-store@0.2.3': {} @@ -14684,16 +14685,16 @@ snapshots: '@smithy/util-middleware': 4.2.14 tslib: 2.8.1 - '@smithy/middleware-retry@4.5.5': + '@smithy/middleware-retry@4.5.7': dependencies: '@smithy/core': 3.23.17 '@smithy/node-config-provider': 4.3.14 '@smithy/protocol-http': 5.3.14 - '@smithy/service-error-classification': 4.3.0 + '@smithy/service-error-classification': 4.3.1 '@smithy/smithy-client': 4.12.13 '@smithy/types': 4.14.1 '@smithy/util-middleware': 4.2.14 - '@smithy/util-retry': 4.3.4 + '@smithy/util-retry': 4.3.6 '@smithy/uuid': 1.1.2 tslib: 2.8.1 @@ -14744,7 +14745,7 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/service-error-classification@4.3.0': + '@smithy/service-error-classification@4.3.1': dependencies: '@smithy/types': 4.14.1 @@ -14844,9 +14845,9 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/util-retry@4.3.4': + '@smithy/util-retry@4.3.6': dependencies: - '@smithy/service-error-classification': 4.3.0 + '@smithy/service-error-classification': 4.3.1 '@smithy/types': 4.14.1 tslib: 2.8.1 @@ -14875,7 +14876,7 @@ snapshots: '@smithy/util-buffer-from': 4.2.2 tslib: 2.8.1 - '@smithy/util-waiter@4.2.16': + '@smithy/util-waiter@4.3.0': dependencies: '@smithy/types': 4.14.1 tslib: 2.8.1 @@ -17735,7 +17736,7 @@ snapshots: dependencies: path-expression-matcher: 1.5.0 - fast-xml-parser@5.7.1: + fast-xml-parser@5.7.2: dependencies: '@nodable/entities': 2.1.0 fast-xml-builder: 1.1.5 From fcef0c6b96dc2273e34e6211ab95bd94ef8df618 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Mon, 4 May 2026 20:57:35 +0100 Subject: [PATCH 19/63] fix: S3 --- .../src/integrations/environment/environment.service.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/server/src/integrations/environment/environment.service.ts b/apps/server/src/integrations/environment/environment.service.ts index f0b548ab7..d9ef01abb 100644 --- a/apps/server/src/integrations/environment/environment.service.ts +++ b/apps/server/src/integrations/environment/environment.service.ts @@ -112,7 +112,10 @@ export class EnvironmentService { } getAwsS3ForcePathStyle(): boolean { - return this.configService.get('AWS_S3_FORCE_PATH_STYLE'); + const forcePathStyle = this.configService + .get('AWS_S3_FORCE_PATH_STYLE', 'false') + .toLowerCase(); + return forcePathStyle === 'true'; } getAwsS3Url(): string { From fe18f22dc685c4406d0715eb271052ec2581e0d1 Mon Sep 17 00:00:00 2001 From: Sarthak Chaturvedi <84394327+mayhemking007@users.noreply.github.com> Date: Tue, 5 May 2026 01:44:21 +0530 Subject: [PATCH 20/63] fix: prevent code block deletion when adding inline comments in read mode (#2146) --- apps/server/src/collaboration/yjs.util.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/server/src/collaboration/yjs.util.ts b/apps/server/src/collaboration/yjs.util.ts index 863b149a6..c79e5331d 100644 --- a/apps/server/src/collaboration/yjs.util.ts +++ b/apps/server/src/collaboration/yjs.util.ts @@ -62,14 +62,14 @@ function applyMarkToYFragment( ) { let pos = 0; - const processItem = (item: any): boolean => { + const processItem = (item: any, parentNodeName?: string): boolean => { if (pos >= to) return false; if (item instanceof Y.XmlText) { const textLength = item.length; const itemEnd = pos + textLength; - if (itemEnd > from && pos < to) { + if (itemEnd > from && pos < to && parentNodeName !== 'codeBlock') { const formatFrom = Math.max(0, from - pos); const formatTo = Math.min(textLength, to - pos); const formatLength = formatTo - formatFrom; @@ -82,7 +82,7 @@ function applyMarkToYFragment( } else if (item instanceof Y.XmlElement) { pos++; // Opening tag for (let i = 0; i < item.length; i++) { - if (!processItem(item.get(i))) return false; + if (!processItem(item.get(i), item.nodeName)) return false; } pos++; // Closing tag } From dbe6c2d6baf60d7d3abfcb191da31b29157f568c Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Mon, 4 May 2026 21:21:37 +0100 Subject: [PATCH 21/63] feat: A11y fixes (#2148) --- .../public/locales/en-US/translation.json | 28 ++++++- .../src/components/common/avatar-uploader.tsx | 10 +++ apps/client/src/components/common/copy.tsx | 1 + .../src/components/common/recent-changes.tsx | 6 +- .../src/components/common/search-input.tsx | 3 + .../components/icons/icon-people-circle.tsx | 6 +- .../layouts/global/app-shell.module.css | 18 ++++ .../layouts/global/global-app-shell.tsx | 37 ++++++++- .../layouts/global/global-sidebar.module.css | 2 +- .../layouts/global/global-sidebar.tsx | 12 +-- .../src/components/settings/app-version.tsx | 2 +- .../components/settings/settings-sidebar.tsx | 61 +++++++------- .../src/components/ui/custom-avatar.tsx | 34 +++++++- .../ui/destination-picker/page-children.tsx | 13 ++- .../client/src/components/ui/emoji-picker.tsx | 9 +- .../components/ai-chat-sidebar-item.tsx | 1 + .../ee/api-key/components/api-key-table.tsx | 8 +- .../components/page-verification-modal.tsx | 22 ++++- .../ee/scim/components/scim-token-table.tsx | 2 +- .../security/components/sso-provider-list.tsx | 9 +- .../ee/template/components/template-card.tsx | 1 + .../components/template-preview-modal.tsx | 2 +- .../comment/components/comment-dialog.tsx | 1 + .../comment/components/comment-list-item.tsx | 9 ++ .../comment/components/comment-menu.tsx | 6 +- .../editor/components/audio/audio-view.tsx | 4 +- .../components/bubble-menu/color-selector.tsx | 83 +++++++++++++------ .../components/bubble-menu/node-selector.tsx | 3 + .../bubble-menu/text-alignment-selector.tsx | 3 + .../editor/components/drawio/drawio-view.tsx | 8 +- .../components/emoji-menu/emoji-list.tsx | 16 +++- .../components/link/link-editor-panel.tsx | 17 ++++ .../components/mention/mention-list.tsx | 27 +++++- .../editor/components/pdf/pdf-view.tsx | 15 +++- .../search-and-replace-dialog.tsx | 28 ++++++- .../components/slash-menu/command-list.tsx | 40 ++++++--- .../editor/components/status/status-view.tsx | 19 +++++ .../editor/components/video/video-view.tsx | 4 +- .../favorite/components/star-button.tsx | 12 +-- .../group/components/group-action-menu.tsx | 2 +- .../group/components/group-members.tsx | 2 +- .../home/components/created-by-me.tsx | 6 +- .../home/components/favorites-pages.tsx | 6 +- .../components/notification-popover.tsx | 3 + .../page-history/components/history-modal.tsx | 2 + .../components/breadcrumbs/breadcrumb.tsx | 33 ++++++-- .../components/header/page-header-menu.tsx | 20 ++++- .../page/components/page-import-modal.tsx | 37 ++++++++- .../components/trash-page-content-modal.tsx | 2 +- .../features/page/trash/components/trash.tsx | 2 +- .../page/tree/components/space-tree.tsx | 8 ++ .../search/components/search-control.tsx | 1 + .../session/components/session-list.tsx | 4 +- .../share/components/share-action-menu.tsx | 2 +- .../features/share/components/share-shell.tsx | 2 + .../space/components/space-members.tsx | 2 +- .../spaces-page/all-spaces-list.tsx | 18 ++-- .../components/members-action-menu.tsx | 6 +- .../components/workspace-invites-table.tsx | 1 + .../components/workspace-members-table.tsx | 1 + .../src/pages/favorites/favorites-page.tsx | 6 +- apps/client/src/theme.ts | 2 +- 62 files changed, 587 insertions(+), 163 deletions(-) diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index 56709bbe6..38fd5f2df 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -416,6 +416,7 @@ "{{latestVersion}} is available": "{{latestVersion}} is available", "Default page edit mode": "Default page edit mode", "Choose your preferred page edit mode. Avoid accidental edits.": "Choose your preferred page edit mode. Avoid accidental edits.", + "Choose {{format}} file": "Choose {{format}} file", "Reading": "Reading", "Delete member": "Delete member", "Member deleted successfully": "Member deleted successfully", @@ -900,5 +901,30 @@ "SCIM tokens": "SCIM tokens", "This action cannot be undone. Your identity provider will stop syncing immediately.": "This action cannot be undone. Your identity provider will stop syncing immediately.", "Toggle SCIM provisioning": "Toggle SCIM provisioning", - "Token": "Token" + "Token": "Token", + "Page menu": "Page menu", + "Expand": "Expand", + "Collapse": "Collapse", + "Comment menu": "Comment menu", + "Group menu": "Group menu", + "Show hidden breadcrumbs": "Show hidden breadcrumbs", + "Breadcrumbs": "Breadcrumbs", + "Page actions": "Page actions", + "Pick emoji": "Pick emoji", + "Template menu": "Template menu", + "Chat menu": "Chat menu", + "API key menu": "API key menu", + "Jump to comment selection": "Jump to comment selection", + "Slash commands": "Slash commands", + "Mention suggestions": "Mention suggestions", + "Link suggestions": "Link suggestions", + "Diagram editor": "Diagram editor", + "Add comment": "Add comment", + "Find and replace": "Find and replace", + "Main navigation": "Main navigation", + "Space navigation": "Space navigation", + "Settings navigation": "Settings navigation", + "AI navigation": "AI navigation", + "Breadcrumb": "Breadcrumb", + "Skip to main content": "Skip to main content" } diff --git a/apps/client/src/components/common/avatar-uploader.tsx b/apps/client/src/components/common/avatar-uploader.tsx index 8d9552f64..750e4ba68 100644 --- a/apps/client/src/components/common/avatar-uploader.tsx +++ b/apps/client/src/components/common/avatar-uploader.tsx @@ -80,6 +80,12 @@ export default function AvatarUploader({ } }; + const ariaLabel = { + [AvatarIconType.AVATAR]: t("Change avatar"), + [AvatarIconType.SPACE_ICON]: t("Change space icon"), + [AvatarIconType.WORKSPACE_ICON]: t("Change workspace icon"), + }[type]; + const handleRemove = async () => { if (disabled) return; @@ -104,6 +110,8 @@ export default function AvatarUploader({ ref={fileInputRef} onChange={handleFileInputChange} accept="image/png,image/jpeg,image/jpg" + aria-label={ariaLabel} + tabIndex={-1} style={{ display: "none" }} /> @@ -115,6 +123,8 @@ export default function AvatarUploader({ size={size} avatarUrl={currentImageUrl} name={fallbackName} + aria-label={ariaLabel} + aria-haspopup="menu" style={{ cursor: disabled || isLoading ? "default" : "pointer", opacity: isLoading ? 0.6 : 1, diff --git a/apps/client/src/components/common/copy.tsx b/apps/client/src/components/common/copy.tsx index 745fc4ba6..2144417b9 100644 --- a/apps/client/src/components/common/copy.tsx +++ b/apps/client/src/components/common/copy.tsx @@ -25,6 +25,7 @@ export default function CopyTextButton({ text, size }: CopyProps) { variant="subtle" onClick={copy} size={size} + aria-label={copied ? t("Copied") : t("Copy")} > {copied ? : } diff --git a/apps/client/src/components/common/recent-changes.tsx b/apps/client/src/components/common/recent-changes.tsx index 277ceb811..8e0e56f29 100644 --- a/apps/client/src/components/common/recent-changes.tsx +++ b/apps/client/src/components/common/recent-changes.tsx @@ -4,7 +4,7 @@ import { UnstyledButton, Badge, Table, - ActionIcon, + ThemeIcon, Button, } from "@mantine/core"; import { Link } from "react-router-dom"; @@ -49,9 +49,9 @@ export default function RecentChanges({ spaceId }: Props) { > {page.icon || ( - + - + )} diff --git a/apps/client/src/components/common/search-input.tsx b/apps/client/src/components/common/search-input.tsx index 08cbbee06..27e50fd4e 100644 --- a/apps/client/src/components/common/search-input.tsx +++ b/apps/client/src/components/common/search-input.tsx @@ -6,12 +6,14 @@ import { useTranslation } from "react-i18next"; export interface SearchInputProps { placeholder?: string; + ariaLabel?: string; debounceDelay?: number; onSearch: (value: string) => void; } export function SearchInput({ placeholder, + ariaLabel, debounceDelay = 500, onSearch, }: SearchInputProps) { @@ -28,6 +30,7 @@ export function SearchInput({ } value={value} onChange={(e) => setValue(e.currentTarget.value)} diff --git a/apps/client/src/components/icons/icon-people-circle.tsx b/apps/client/src/components/icons/icon-people-circle.tsx index 996958965..1a2daf73d 100644 --- a/apps/client/src/components/icons/icon-people-circle.tsx +++ b/apps/client/src/components/icons/icon-people-circle.tsx @@ -1,11 +1,11 @@ -import { ActionIcon, rem } from "@mantine/core"; +import { ThemeIcon } from "@mantine/core"; import React from "react"; import { IconUsersGroup } from "@tabler/icons-react"; export function IconGroupCircle() { return ( - + - + ); } diff --git a/apps/client/src/components/layouts/global/app-shell.module.css b/apps/client/src/components/layouts/global/app-shell.module.css index ed369612c..7ed937727 100644 --- a/apps/client/src/components/layouts/global/app-shell.module.css +++ b/apps/client/src/components/layouts/global/app-shell.module.css @@ -28,4 +28,22 @@ } } +.skipLink { + position: fixed; + left: 8px; + top: 8px; + padding: 8px 12px; + background: var(--mantine-color-blue-6); + color: #fff; + border-radius: 4px; + text-decoration: none; + z-index: 1000; + transform: translateY(-150%); + + &:focus { + transform: translateY(0); + outline: 2px solid var(--mantine-color-blue-3); + } +} + diff --git a/apps/client/src/components/layouts/global/global-app-shell.tsx b/apps/client/src/components/layouts/global/global-app-shell.tsx index 6e842a056..99373814a 100644 --- a/apps/client/src/components/layouts/global/global-app-shell.tsx +++ b/apps/client/src/components/layouts/global/global-app-shell.tsx @@ -1,6 +1,7 @@ import { AppShell, Container } from "@mantine/core"; import React, { useEffect, useRef, useState } from "react"; import { useLocation } from "react-router-dom"; +import { useTranslation } from "react-i18next"; import SettingsSidebar from "@/components/settings/settings-sidebar.tsx"; import { useAtom } from "jotai"; import { @@ -23,11 +24,12 @@ export default function GlobalAppShell({ }: { children: React.ReactNode; }) { + const { t } = useTranslation(); useTrialEndAction(); const [mobileOpened] = useAtom(mobileSidebarAtom); const toggleMobile = useToggleSidebar(mobileSidebarAtom); const [desktopOpened] = useAtom(desktopSidebarAtom); - const [{ isAsideOpen }] = useAtom(asideStateAtom); + const [{ isAsideOpen, tab: asideTab }] = useAtom(asideStateAtom); const [sidebarWidth, setSidebarWidth] = useAtom(sidebarWidthAtom); const [isResizing, setIsResizing] = useState(false); const sidebarRef = useRef(null); @@ -79,7 +81,11 @@ export default function GlobalAppShell({ const showGlobalSidebar = !isSpaceRoute && !isSettingsRoute && !isAiRoute; return ( - + + {t("Skip to main content")} + + {isSpaceRoute && (
@@ -114,7 +129,7 @@ export default function GlobalAppShell({ {isAiRoute && } {showGlobalSidebar && } - + {isSettingsRoute ? ( {children} @@ -125,10 +140,24 @@ export default function GlobalAppShell({ {isPageRoute && ( - +
may have been replaced by a PM transaction; drop + // the cached reference before checking eligibility. + this.cachedHeaderRow = null; + if (!this.isEligible()) { + this.apply('off'); + return; + } + if (this.mode === 'off') { + // Eligibility just flipped back on; re-trigger the observer so it + // emits the current intersection state. + this.fitsObserver?.unobserve(this.table); + this.fitsObserver?.observe(this.table); + } + } + + destroy() { + this.fitsObserver?.disconnect(); + this.fitsObserver = undefined; + this.apply('off'); + pinOffsetWatcher.release(); + } +} + +const controllers = new WeakMap(); + +export function attach(wrapper: HTMLElement) { + if (controllers.has(wrapper)) return; + const table = wrapper.querySelector(':scope > table') as HTMLTableElement | null; + if (!table) return; + controllers.set(wrapper, new TablePinController(wrapper, table)); +} + +export function detach(wrapper: HTMLElement) { + const ctrl = controllers.get(wrapper); + if (!ctrl) return; + ctrl.destroy(); + controllers.delete(wrapper); +} + +export function getController(wrapper: HTMLElement): TablePinController | undefined { + return controllers.get(wrapper); +} diff --git a/packages/editor-ext/src/lib/table/header-pin/extension.ts b/packages/editor-ext/src/lib/table/header-pin/extension.ts new file mode 100644 index 000000000..8e5157ede --- /dev/null +++ b/packages/editor-ext/src/lib/table/header-pin/extension.ts @@ -0,0 +1,78 @@ +import { Extension } from '@tiptap/core'; +import { Plugin, PluginKey } from '@tiptap/pm/state'; + +import { attach, detach, getController } from './controller'; + +const tableHeaderPinKey = new PluginKey('tableHeaderPin'); + +export const TableHeaderPin = Extension.create({ + name: 'tableHeaderPin', + + addProseMirrorPlugins() { + let editorRoot: HTMLElement | null = null; + let domObserver: MutationObserver | null = null; + const tracked = new Set(); + let rafHandle: number | null = null; + + const reconcile = () => { + rafHandle = null; + if (!editorRoot) return; + const current = new Set( + editorRoot.querySelectorAll('.tableWrapper'), + ); + for (const w of tracked) { + if (!current.has(w)) { + detach(w); + tracked.delete(w); + } + } + for (const w of current) { + if (!tracked.has(w)) { + attach(w); + tracked.add(w); + } + } + }; + + const schedule = () => { + if (rafHandle !== null) return; + rafHandle = requestAnimationFrame(reconcile); + }; + + return [ + new Plugin({ + key: tableHeaderPinKey, + + view(editorView) { + editorRoot = editorView.dom as HTMLElement; + + schedule(); + + domObserver = new MutationObserver(schedule); + domObserver.observe(editorRoot, { subtree: true, childList: true }); + + return { + update(view, prevState) { + if (!editorRoot) return; + if (view.state.doc === prevState.doc) return; + editorRoot + .querySelectorAll('.tableWrapper') + .forEach((w) => getController(w)?.refresh()); + }, + destroy() { + if (rafHandle !== null) { + cancelAnimationFrame(rafHandle); + rafHandle = null; + } + domObserver?.disconnect(); + domObserver = null; + for (const w of tracked) detach(w); + tracked.clear(); + editorRoot = null; + }, + }; + }, + }), + ]; + }, +}); diff --git a/packages/editor-ext/src/lib/table/header-pin/index.ts b/packages/editor-ext/src/lib/table/header-pin/index.ts new file mode 100644 index 000000000..b45e01aee --- /dev/null +++ b/packages/editor-ext/src/lib/table/header-pin/index.ts @@ -0,0 +1 @@ +export { TableHeaderPin } from './extension'; diff --git a/packages/editor-ext/src/lib/table/header-pin/offset.ts b/packages/editor-ext/src/lib/table/header-pin/offset.ts new file mode 100644 index 000000000..89cc6bf9e --- /dev/null +++ b/packages/editor-ext/src/lib/table/header-pin/offset.ts @@ -0,0 +1,65 @@ +// Pin-offset measurement and watcher used by the table header-pin controller. + +// Fallback app-bar height (px) when no fixed surface is mounted; matches global-app-shell.tsx. +const APP_BAR_FALLBACK_HEIGHT = 45; + +export const EDITOR_PIN_OFFSET_VAR = '--editor-pin-offset'; + +// Selectors for fixed surfaces between viewport top and editor content. Use data attributes — +// CSS module classes are build-time hashed and won't match. +const PIN_ANCHOR_SELECTORS = [ + '[data-page-header]', + '[data-fixed-toolbar]', +] as const; + +export function computePinTop(): number { + let bottom = APP_BAR_FALLBACK_HEIGHT; + for (const sel of PIN_ANCHOR_SELECTORS) { + const el = document.querySelector(sel) as HTMLElement | null; + if (!el) continue; + const rect = el.getBoundingClientRect(); + if (rect.height > 0 && rect.bottom > bottom) bottom = rect.bottom; + } + return bottom; +} + +// Reference-counted watcher that publishes the editor's top offset to a CSS custom property. +export const pinOffsetWatcher = { + refs: 0, + resizeObserver: null as ResizeObserver | null, + rafPending: false, + lastValue: -1, + + acquire() { + if (this.refs++ > 0) return; + this.publish(); + const schedule = () => { + if (this.rafPending) return; + this.rafPending = true; + requestAnimationFrame(() => { + this.rafPending = false; + this.publish(); + }); + }; + this.resizeObserver = new ResizeObserver(schedule); + this.resizeObserver.observe(document.body); + }, + + release() { + if (--this.refs > 0) return; + this.resizeObserver?.disconnect(); + this.resizeObserver = null; + document.documentElement.style.removeProperty(EDITOR_PIN_OFFSET_VAR); + this.lastValue = -1; + }, + + publish() { + const top = computePinTop(); + if (top === this.lastValue) return; + this.lastValue = top; + document.documentElement.style.setProperty( + EDITOR_PIN_OFFSET_VAR, + `${top}px`, + ); + }, +}; diff --git a/packages/editor-ext/src/lib/table/index.ts b/packages/editor-ext/src/lib/table/index.ts index 9e5a92651..ed06582e3 100644 --- a/packages/editor-ext/src/lib/table/index.ts +++ b/packages/editor-ext/src/lib/table/index.ts @@ -2,4 +2,14 @@ export * from "./row"; export * from "./cell"; export * from "./header"; export * from "./table"; -export * from "./dnd"; \ No newline at end of file +export * from "./dnd"; +export * from "./table-view"; +export * from "./header-pin"; +export * from "./table-readonly-sort"; +export { moveColumn } from "./utils/move-column"; +export type { MoveColumnParams } from "./utils/move-column"; +export { moveRow } from "./utils/move-row"; +export type { MoveRowParams } from "./utils/move-row"; +export { convertTableNodeToArrayOfRows } from "./utils/convert-table-node-to-array-of-rows"; +export { convertArrayOfRowsToTableNode } from "./utils/convert-array-of-rows-to-table-node"; +export { transpose } from "./utils/transpose"; diff --git a/packages/editor-ext/src/lib/table/table-readonly-sort.ts b/packages/editor-ext/src/lib/table/table-readonly-sort.ts new file mode 100644 index 000000000..3e246a411 --- /dev/null +++ b/packages/editor-ext/src/lib/table/table-readonly-sort.ts @@ -0,0 +1,233 @@ +import { Extension } from '@tiptap/core'; +import { Plugin, PluginKey } from '@tiptap/pm/state'; + +type SortDirection = 'asc' | 'desc'; + +type SortState = { + col: number; + direction: SortDirection; +}; + +const CHEVRON_CLASS = 'tableReadonlySortChevron'; + +const tableReadonlySortKey = new PluginKey('tableReadonlySort'); + +const sortStates = new WeakMap(); +const originalOrders = new WeakMap(); + +const collator = new Intl.Collator(undefined, { sensitivity: 'base', numeric: true }); + +function getColumnIndex(th: HTMLTableCellElement): number { + const row = th.parentElement as HTMLTableRowElement; + if (!row) return -1; + let col = 0; + for (let i = 0; i < row.cells.length; i++) { + if (row.cells[i] === th) return col; + col += row.cells[i].colSpan ?? 1; + } + return -1; +} + +function getHeaderTh(target: EventTarget | null): HTMLTableCellElement | null { + if (!(target instanceof Element)) return null; + const th = target.closest('th') as HTMLTableCellElement | null; + if (!th) return null; + const row = th.parentElement; + if (!row) return null; + const tbody = row.parentElement; + if (!tbody) return null; + const table = tbody.closest('table'); + if (!table) return null; + + // th must be in the first row of the table (could be in thead or tbody) + const firstRow = table.querySelector('tr'); + if (firstRow !== row) return null; + + return th; +} + +function getCellText(row: HTMLTableRowElement, colIndex: number): string { + let col = 0; + for (let i = 0; i < row.cells.length; i++) { + if (col === colIndex) return row.cells[i].textContent?.trim() ?? ''; + col += row.cells[i].colSpan ?? 1; + } + return ''; +} + +function getOrSaveOriginalOrder( + table: HTMLTableElement, + dataRows: HTMLTableRowElement[], +): HTMLTableRowElement[] { + if (!originalOrders.has(table)) { + originalOrders.set(table, [...dataRows]); + } + return originalOrders.get(table)!; +} + +function sortDataRows( + dataRows: HTMLTableRowElement[], + colIndex: number, + direction: SortDirection, +): HTMLTableRowElement[] { + return [...dataRows].sort((a, b) => { + const textA = getCellText(a, colIndex); + const textB = getCellText(b, colIndex); + const emptyA = textA === ''; + const emptyB = textB === ''; + if (emptyA && emptyB) return 0; + if (emptyA) return 1; + if (emptyB) return -1; + const cmp = collator.compare(textA, textB); + return direction === 'asc' ? cmp : -cmp; + }); +} + +function applySort(table: HTMLTableElement, colIndex: number): void { + const tbody = table.querySelector('tbody'); + if (!tbody) return; + + const allRows = Array.from(tbody.querySelectorAll(':scope > tr')); + if (allRows.length === 0) return; + + const headerRow = allRows[0]; + const dataRows = allRows.slice(1); + if (dataRows.length === 0) return; + + const current = sortStates.get(table) ?? null; + const saved = getOrSaveOriginalOrder(table, dataRows); + + let next: SortState | null; + if (!current || current.col !== colIndex) { + next = { col: colIndex, direction: 'asc' }; + } else if (current.direction === 'asc') { + next = { col: colIndex, direction: 'desc' }; + } else { + next = null; + } + + if (next === null) { + sortStates.delete(table); + tbody.append(headerRow, ...saved); + } else { + sortStates.set(table, next); + const sorted = sortDataRows(saved, next.col, next.direction); + tbody.append(headerRow, ...sorted); + } + + updateChevrons(table); +} + +const CHEVRON_SVG = + ''; + +function ensureChevron(th: HTMLTableCellElement): HTMLSpanElement { + let chevron = th.querySelector(`.${CHEVRON_CLASS}`); + if (!chevron) { + chevron = document.createElement('span'); + chevron.className = CHEVRON_CLASS; + chevron.setAttribute('aria-hidden', 'true'); + chevron.innerHTML = CHEVRON_SVG; + th.appendChild(chevron); + } + return chevron; +} + +function updateChevrons(table: HTMLTableElement): void { + const firstRow = table.querySelector('tr'); + if (!firstRow) return; + + const state = sortStates.get(table) ?? null; + let col = 0; + for (let i = 0; i < firstRow.cells.length; i++) { + const cell = firstRow.cells[i]; + if (cell.tagName !== 'TH') { + col += cell.colSpan ?? 1; + continue; + } + const chevron = ensureChevron(cell as HTMLTableCellElement); + let label: string; + if (state && state.col === col) { + chevron.setAttribute('data-sort', state.direction); + label = state.direction === 'asc' ? 'Sort descending' : 'Clear sort'; + } else { + chevron.removeAttribute('data-sort'); + label = 'Sort ascending'; + } + chevron.setAttribute('data-tooltip', label); + chevron.setAttribute('aria-label', label); + chevron.title = label; + col += cell.colSpan ?? 1; + } +} + +function addChevronsToAllTables(editorRoot: HTMLElement): void { + const tables = editorRoot.querySelectorAll('table'); + tables.forEach((table) => updateChevrons(table)); +} + +function removeAllChevrons(editorRoot: HTMLElement): void { + editorRoot + .querySelectorAll(`.${CHEVRON_CLASS}`) + .forEach((el) => el.remove()); +} + +export const TableReadonlySort = Extension.create({ + name: 'tableReadonlySort', + + addProseMirrorPlugins() { + const editor = this.editor; + let editorRoot: HTMLElement | null = null; + + const onClick = (event: MouseEvent) => { + if (editor.isEditable) return; + // Only react to clicks on the chevron, not anywhere else in the header + // cell. This lets the user click into a header to select text without + // accidentally triggering a sort. + if (!(event.target instanceof Element)) return; + const chevron = event.target.closest(`.${CHEVRON_CLASS}`); + if (!chevron) return; + const th = getHeaderTh(chevron); + if (!th) return; + const table = th.closest('table') as HTMLTableElement | null; + if (!table) return; + const colIndex = getColumnIndex(th); + if (colIndex < 0) return; + applySort(table, colIndex); + }; + + return [ + new Plugin({ + key: tableReadonlySortKey, + + view(editorView) { + editorRoot = editorView.dom as HTMLElement; + editorRoot.addEventListener('click', onClick); + + if (!editor.isEditable) { + addChevronsToAllTables(editorRoot); + } + + return { + update(view) { + const root = view.dom as HTMLElement; + if (!editor.isEditable) { + addChevronsToAllTables(root); + } else { + removeAllChevrons(root); + } + }, + destroy() { + if (editorRoot) { + editorRoot.removeEventListener('click', onClick); + removeAllChevrons(editorRoot); + } + }, + }; + }, + }), + ]; + }, +}); diff --git a/packages/editor-ext/src/lib/table/table-view.ts b/packages/editor-ext/src/lib/table/table-view.ts new file mode 100644 index 000000000..7e410918e --- /dev/null +++ b/packages/editor-ext/src/lib/table/table-view.ts @@ -0,0 +1,158 @@ +import type { Node as ProseMirrorNode } from '@tiptap/pm/model'; +import type { NodeView, ViewMutationRecord } from '@tiptap/pm/view'; +import { getColStyleDeclaration } from './utils/col-style'; + +export function updateColumns( + node: ProseMirrorNode, + colgroup: HTMLElement, + table: HTMLTableElement, + cellMinWidth: number, + overrideCol?: number, + overrideValue?: number, +) { + let totalWidth = 0; + let fixedWidth = true; + let nextDOM = colgroup.firstChild; + const row = node.firstChild; + + if (row !== null) { + for (let i = 0, col = 0; i < row.childCount; i += 1) { + const { colspan, colwidth } = row.child(i).attrs; + + for (let j = 0; j < colspan; j += 1, col += 1) { + const hasWidth = + overrideCol === col + ? overrideValue + : ((colwidth && colwidth[j]) as number | undefined); + const cssWidth = hasWidth ? `${hasWidth}px` : ''; + + totalWidth += hasWidth || cellMinWidth; + + if (!hasWidth) { + fixedWidth = false; + } + + if (!nextDOM) { + const colElement = document.createElement('col'); + + const [propertyKey, propertyValue] = getColStyleDeclaration( + cellMinWidth, + hasWidth, + ); + + colElement.style.setProperty(propertyKey, propertyValue); + + colgroup.appendChild(colElement); + } else { + if ((nextDOM as HTMLTableColElement).style.width !== cssWidth) { + const [propertyKey, propertyValue] = getColStyleDeclaration( + cellMinWidth, + hasWidth, + ); + + (nextDOM as HTMLTableColElement).style.setProperty( + propertyKey, + propertyValue, + ); + } + + nextDOM = nextDOM.nextSibling; + } + } + } + } + + while (nextDOM) { + const after = nextDOM.nextSibling; + + nextDOM.parentNode?.removeChild(nextDOM); + nextDOM = after; + } + + const hasUserWidth = + node.attrs.style && + typeof node.attrs.style === 'string' && + /\bwidth\s*:/i.test(node.attrs.style); + + if (fixedWidth && !hasUserWidth) { + table.style.width = `${totalWidth}px`; + table.style.minWidth = ''; + } else { + table.style.width = ''; + table.style.minWidth = `${totalWidth}px`; + } +} + +export class TableView implements NodeView { + node: ProseMirrorNode; + + cellMinWidth: number; + + dom: HTMLDivElement; + + table: HTMLTableElement; + + colgroup: HTMLTableColElement; + + contentDOM: HTMLTableSectionElement; + + constructor(node: ProseMirrorNode, cellMinWidth: number) { + this.node = node; + this.cellMinWidth = cellMinWidth; + this.dom = document.createElement('div'); + this.dom.className = 'tableWrapper'; + this.table = this.dom.appendChild(document.createElement('table')); + + if (node.attrs.style) { + this.table.style.cssText = node.attrs.style; + } + + this.colgroup = this.table.appendChild(document.createElement('colgroup')); + updateColumns(node, this.colgroup, this.table, cellMinWidth); + this.contentDOM = this.table.appendChild(document.createElement('tbody')); + } + + update(node: ProseMirrorNode) { + if (node.type !== this.node.type) return false; + + this.node = node; + updateColumns(node, this.colgroup, this.table, this.cellMinWidth); + + return true; + } + + ignoreMutation(mutation: ViewMutationRecord) { + const target = mutation.target as Node; + const isInsideWrapper = this.dom.contains(target); + const isInsideContent = this.contentDOM.contains(target); + + if (isInsideWrapper && !isInsideContent) { + if ( + mutation.type === 'attributes' || + mutation.type === 'childList' || + mutation.type === 'characterData' + ) { + return true; + } + } + + // Chevron span (.tableReadonlySortChevron) added/removed by sort plugin. + if (mutation.type === 'childList') { + const nodes = [ + ...Array.from(mutation.addedNodes), + ...Array.from(mutation.removedNodes), + ]; + if ( + nodes.some( + (n) => + n instanceof Element && + n.classList.contains('tableReadonlySortChevron'), + ) + ) { + return true; + } + } + + return false; + } +} diff --git a/packages/editor-ext/src/lib/table/table.ts b/packages/editor-ext/src/lib/table/table.ts index f1436c28d..e87048a46 100644 --- a/packages/editor-ext/src/lib/table/table.ts +++ b/packages/editor-ext/src/lib/table/table.ts @@ -1,6 +1,8 @@ import { Table } from "@tiptap/extension-table"; import { Editor } from "@tiptap/core"; import { DOMOutputSpec } from "@tiptap/pm/model"; +import { TextSelection } from "@tiptap/pm/state"; +import { cellAround } from "@tiptap/pm/tables"; const LIST_TYPES = ["bulletList", "orderedList", "taskList"]; @@ -32,9 +34,36 @@ function handleListOutdent(editor: Editor): boolean { } export const CustomTable = Table.extend({ + addKeyboardShortcuts() { return { ...this.parent?.(), + "Mod-a": () => { + const { state, view } = this.editor; + const { selection, doc } = state; + + const $cellPos = cellAround(selection.$anchor); + if (!$cellPos) return false; + + const cellNode = doc.nodeAt($cellPos.pos); + // Empty cells have nothing useful to scope to — let the default + // Mod-a fall through and select the whole doc. + if (!cellNode || !cellNode.textContent) return false; + + const from = $cellPos.pos + 1; + const to = $cellPos.pos + cellNode.nodeSize - 1; + if (from >= to) return true; + + const nextSel = TextSelection.between( + doc.resolve(from), + doc.resolve(to), + 1, + ); + if (!nextSel || selection.eq(nextSel)) return true; + + view.dispatch(state.tr.setSelection(nextSel)); + return true; + }, Tab: () => { // If we're in a list within a table, handle list indentation if (isInList(this.editor) && this.editor.isActive("table")) { diff --git a/packages/editor-ext/src/lib/table/utils/col-style.ts b/packages/editor-ext/src/lib/table/utils/col-style.ts new file mode 100644 index 000000000..8060962fd --- /dev/null +++ b/packages/editor-ext/src/lib/table/utils/col-style.ts @@ -0,0 +1,7 @@ +export function getColStyleDeclaration(minWidth: number, width: number | undefined): [string, string] { + if (width) { + return ['width', `${Math.max(width, minWidth)}px`] + } + + return ['min-width', `${minWidth}px`] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a6dd37f6..f4a628064 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -248,22 +248,22 @@ importers: apps/client: dependencies: '@atlaskit/pragmatic-drag-and-drop': - specifier: ^1.8.1 + specifier: 1.8.1 version: 1.8.1 '@atlaskit/pragmatic-drag-and-drop-auto-scroll': - specifier: ^2.1.0 + specifier: 2.1.5 version: 2.1.5 '@atlaskit/pragmatic-drag-and-drop-flourish': - specifier: ^2.0.15 + specifier: 2.0.15 version: 2.0.15(react@18.3.1) '@atlaskit/pragmatic-drag-and-drop-hitbox': - specifier: ^1.1.0 + specifier: 1.1.0 version: 1.1.0 '@atlaskit/pragmatic-drag-and-drop-live-region': - specifier: ^1.3.4 + specifier: 1.3.4 version: 1.3.4 '@casl/react': - specifier: ^5.0.1 + specifier: 5.0.1 version: 5.0.1(@casl/ability@6.8.0)(react@18.3.1) '@docmost/editor-ext': specifier: workspace:* @@ -272,37 +272,37 @@ importers: specifier: 0.18.0-3a5ef40 version: 0.18.0-3a5ef40(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mantine/core': - specifier: ^8.3.18 + specifier: 8.3.18 version: 8.3.18(@mantine/hooks@8.3.18(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mantine/dates': - specifier: ^8.3.18 + specifier: 8.3.18 version: 8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@8.3.18(react@18.3.1))(dayjs@1.11.19)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mantine/form': - specifier: ^8.3.18 + specifier: 8.3.18 version: 8.3.18(react@18.3.1) '@mantine/hooks': - specifier: ^8.3.18 + specifier: 8.3.18 version: 8.3.18(react@18.3.1) '@mantine/modals': - specifier: ^8.3.18 + specifier: 8.3.18 version: 8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@8.3.18(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mantine/notifications': - specifier: ^8.3.18 + specifier: 8.3.18 version: 8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@8.3.18(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mantine/spotlight': - specifier: ^8.3.18 + specifier: 8.3.18 version: 8.3.18(@mantine/core@8.3.18(@mantine/hooks@8.3.18(react@18.3.1))(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@mantine/hooks@8.3.18(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@slidoapp/emoji-mart': - specifier: ^5.8.7 + specifier: 5.8.7 version: 5.8.7 '@slidoapp/emoji-mart-data': - specifier: ^1.2.4 + specifier: 1.2.4 version: 1.2.4 '@slidoapp/emoji-mart-react': - specifier: ^1.1.5 + specifier: 1.1.5 version: 1.1.5(@slidoapp/emoji-mart@5.8.7)(react@18.3.1) '@tabler/icons-react': - specifier: ^3.40.0 + specifier: 3.40.0 version: 3.40.0(react@18.3.1) '@tanstack/react-query': specifier: 5.90.17 @@ -311,22 +311,22 @@ importers: specifier: 3.13.24 version: 3.13.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) alfaaz: - specifier: ^1.1.0 + specifier: 1.1.0 version: 1.1.0 axios: specifier: 1.16.0 version: 1.16.0 blueimp-load-image: - specifier: ^5.16.0 + specifier: 5.16.0 version: 5.16.0 clsx: - specifier: ^2.1.1 + specifier: 2.1.1 version: 2.1.1 file-saver: - specifier: ^2.0.5 + specifier: 2.0.5 version: 2.0.5 highlightjs-sap-abap: - specifier: ^0.3.0 + specifier: 0.3.0 version: 0.3.0 i18next: specifier: 25.10.1 @@ -335,37 +335,37 @@ importers: specifier: 3.0.6 version: 3.0.6 jotai: - specifier: ^2.18.1 + specifier: 2.18.1 version: 2.18.1(@babel/core@7.28.5)(@babel/template@7.27.2)(@types/react@18.3.12)(react@18.3.1) jotai-optics: - specifier: ^0.4.0 + specifier: 0.4.0 version: 0.4.0(jotai@2.18.1(@babel/core@7.28.5)(@babel/template@7.27.2)(@types/react@18.3.12)(react@18.3.1))(optics-ts@2.4.1) js-cookie: - specifier: ^3.0.5 + specifier: 3.0.5 version: 3.0.5 jwt-decode: - specifier: ^4.0.0 + specifier: 4.0.0 version: 4.0.0 katex: specifier: 0.16.40 version: 0.16.40 lowlight: - specifier: ^3.3.0 + specifier: 3.3.0 version: 3.3.0 mantine-form-zod-resolver: - specifier: ^1.3.0 + specifier: 1.3.0 version: 1.3.0(@mantine/form@8.3.18(react@18.3.1))(zod@4.3.6) mermaid: specifier: 11.13.0 version: 11.13.0 mitt: - specifier: ^3.0.1 + specifier: 3.0.1 version: 3.0.1 posthog-js: specifier: 1.372.2 version: 1.372.2 react: - specifier: ^18.3.1 + specifier: 18.3.1 version: 18.3.1 react-clear-modal: specifier: ^2.0.18 @@ -374,111 +374,111 @@ importers: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) react-drawio: - specifier: ^1.0.7 + specifier: 1.0.7 version: 1.0.7(react@18.3.1) react-error-boundary: - specifier: ^6.1.1 + specifier: 6.1.1 version: 6.1.1(react@18.3.1) react-helmet-async: - specifier: ^3.0.0 + specifier: 3.0.0 version: 3.0.0(react@18.3.1) react-i18next: specifier: 16.5.8 version: 16.5.8(i18next@25.10.1(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) react-router-dom: - specifier: ^7.13.1 + specifier: 7.13.1 version: 7.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) semver: - specifier: ^7.7.4 + specifier: 7.7.4 version: 7.7.4 socket.io-client: - specifier: ^4.8.3 + specifier: 4.8.3 version: 4.8.3 zod: - specifier: ^4.3.6 + specifier: 4.3.6 version: 4.3.6 devDependencies: '@eslint/js': - specifier: ^9.28.0 - version: 9.39.4 + specifier: 9.28.0 + version: 9.28.0 '@tanstack/eslint-plugin-query': - specifier: ^5.94.4 - version: 5.94.4(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3) + specifier: 5.94.4 + version: 5.94.4(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) '@testing-library/jest-dom': - specifier: ^6.6.0 - version: 6.9.1 + specifier: 6.6.0 + version: 6.6.0 '@testing-library/react': - specifier: ^16.1.0 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 16.1.0 + version: 16.1.0(@testing-library/dom@10.4.1)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/blueimp-load-image': - specifier: ^5.16.6 + specifier: 5.16.6 version: 5.16.6 '@types/file-saver': - specifier: ^2.0.7 + specifier: 2.0.7 version: 2.0.7 '@types/js-cookie': - specifier: ^3.0.6 + specifier: 3.0.6 version: 3.0.6 '@types/katex': - specifier: ^0.16.8 + specifier: 0.16.8 version: 0.16.8 '@types/node': specifier: 22.19.1 version: 22.19.1 '@types/react': - specifier: ^18.3.12 + specifier: 18.3.12 version: 18.3.12 '@types/react-dom': - specifier: ^18.3.1 + specifier: 18.3.1 version: 18.3.1 '@vitejs/plugin-react': - specifier: ^6.0.1 - version: 6.0.1(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 6.0.1 + version: 6.0.1(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)) eslint: - specifier: ^9.28.0 - version: 9.39.4(jiti@2.4.2) + specifier: 9.28.0 + version: 9.28.0(jiti@2.4.2) eslint-plugin-react: - specifier: ^7.37.5 - version: 7.37.5(eslint@9.39.4(jiti@2.4.2)) + specifier: 7.37.5 + version: 7.37.5(eslint@9.28.0(jiti@2.4.2)) eslint-plugin-react-hooks: - specifier: ^7.0.1 - version: 7.0.1(eslint@9.39.4(jiti@2.4.2)) + specifier: 7.0.1 + version: 7.0.1(eslint@9.28.0(jiti@2.4.2)) eslint-plugin-react-refresh: - specifier: ^0.5.2 - version: 0.5.2(eslint@9.39.4(jiti@2.4.2)) + specifier: 0.5.2 + version: 0.5.2(eslint@9.28.0(jiti@2.4.2)) globals: - specifier: ^15.13.0 + specifier: 15.13.0 version: 15.13.0 jsdom: - specifier: ^25.0.0 - version: 25.0.1 + specifier: 25.0.0 + version: 25.0.0 optics-ts: - specifier: ^2.4.1 + specifier: 2.4.1 version: 2.4.1 postcss: - specifier: ^8.5.12 - version: 8.5.12 + specifier: 8.5.14 + version: 8.5.14 postcss-preset-mantine: - specifier: ^1.18.0 - version: 1.18.0(postcss@8.5.12) + specifier: 1.18.0 + version: 1.18.0(postcss@8.5.14) postcss-simple-vars: - specifier: ^7.0.1 - version: 7.0.1(postcss@8.5.12) + specifier: 7.0.1 + version: 7.0.1(postcss@8.5.14) prettier: - specifier: ^3.8.1 + specifier: 3.8.1 version: 3.8.1 typescript: - specifier: ^5.9.3 + specifier: 5.9.3 version: 5.9.3 typescript-eslint: - specifier: ^8.57.1 - version: 8.57.1(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3) + specifier: 8.57.1 + version: 8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) vite: specifier: 8.0.5 - version: 8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) + version: 8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) vitest: - specifier: ^4.1.6 - version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@22.19.1)(happy-dom@20.8.9)(jsdom@25.0.1)(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)) + specifier: 4.1.6 + version: 4.1.6(@opentelemetry/api@1.9.0)(@types/node@22.19.1)(happy-dom@20.8.9)(jsdom@25.0.0)(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)) apps/server: dependencies: @@ -2237,14 +2237,30 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/config-array@0.20.1': + resolution: {integrity: sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-array@0.21.2': resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.2.3': + resolution: {integrity: sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/config-helpers@0.4.2': resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.14.0': + resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.2': + resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@0.17.0': resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2253,6 +2269,10 @@ packages: resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.28.0': + resolution: {integrity: sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.39.4': resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2261,6 +2281,10 @@ packages: resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.3.5': + resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.4.1': resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4463,12 +4487,12 @@ packages: resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} engines: {node: '>=18'} - '@testing-library/jest-dom@6.9.1': - resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + '@testing-library/jest-dom@6.6.0': + resolution: {integrity: sha512-Y76dmd7C85xekWqylJqRmO6lr83cdVprTs0muSvkXr6M73auYK5OvZMc3tKe1F7wMFdzfeBCwVbkoGrRKWb+fg==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - '@testing-library/react@16.3.2': - resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + '@testing-library/react@16.1.0': + resolution: {integrity: sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg==} engines: {node: '>=18'} peerDependencies: '@testing-library/dom': ^10.0.0 @@ -5540,10 +5564,6 @@ packages: resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} engines: {node: '>= 0.4'} - array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - array-buffer-byte-length@1.0.2: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} @@ -5571,10 +5591,6 @@ packages: resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.4: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} @@ -5787,10 +5803,6 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - call-bind@1.0.8: resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} engines: {node: '>= 0.4'} @@ -5825,6 +5837,10 @@ packages: resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -6135,9 +6151,6 @@ packages: resolution: {integrity: sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==} engines: {node: '>=18'} - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -6301,26 +6314,14 @@ packages: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} - data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} - data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} - data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} - data-view-byte-length@1.0.2: resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} engines: {node: '>= 0.4'} - data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} - data-view-byte-offset@1.0.1: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} @@ -6606,10 +6607,6 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - es-abstract@1.23.5: - resolution: {integrity: sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==} - engines: {node: '>= 0.4'} - es-abstract@1.24.1: resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} engines: {node: '>= 0.4'} @@ -6626,9 +6623,6 @@ packages: resolution: {integrity: sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ==} engines: {node: '>= 0.4'} - es-module-lexer@2.0.0: - resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} - es-module-lexer@2.1.0: resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} @@ -6727,6 +6721,16 @@ packages: resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} + eslint@9.28.0: + resolution: {integrity: sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + eslint@9.39.4: resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -6954,9 +6958,6 @@ packages: debug: optional: true - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - for-each@0.3.5: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} @@ -7016,10 +7017,6 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - function.prototype.name@1.1.8: resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} engines: {node: '>= 0.4'} @@ -7059,10 +7056,6 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - get-symbol-description@1.1.0: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} @@ -7137,10 +7130,6 @@ packages: has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - has-proto@1.2.0: resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} engines: {node: '>= 0.4'} @@ -7292,10 +7281,6 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -7326,10 +7311,6 @@ packages: resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} engines: {node: '>= 10'} - is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -7349,10 +7330,6 @@ packages: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} - is-boolean-object@1.2.0: - resolution: {integrity: sha512-kR5g0+dXf/+kXnqI+lu0URKYPKgICtHGGNCDSB10AaUFj3o/HkB3u7WfpRBJGFopxxY0oH3ux7ZsDjLtK7xqvw==} - engines: {node: '>= 0.4'} - is-boolean-object@1.2.2: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} @@ -7364,18 +7341,10 @@ packages: is-core-module@2.13.1: resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} - is-data-view@1.0.2: resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} engines: {node: '>= 0.4'} - is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - is-date-object@1.1.0: resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} engines: {node: '>= 0.4'} @@ -7421,10 +7390,6 @@ packages: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} - is-number-object@1.1.0: - resolution: {integrity: sha512-KVSZV0Dunv9DTPkhXwcZ3Q+tUc9TsaE1ZwX5J2WMvsSGS6Md8TFPun5uwh0yRdrNerI6vf/tbJxqSx4c1ZI1Lw==} - engines: {node: '>= 0.4'} - is-number-object@1.1.1: resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} engines: {node: '>= 0.4'} @@ -7439,10 +7404,6 @@ packages: is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} - is-regex@1.2.0: - resolution: {integrity: sha512-B6ohK4ZmoftlUe+uvenXSbPJFo6U37BH7oO1B3nQH8f/7h27N56s85MhUtbFJAziz5dcmuR3i8ovUl35zp8pFA==} - engines: {node: '>= 0.4'} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -7451,10 +7412,6 @@ packages: resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} engines: {node: '>= 0.4'} - is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - is-shared-array-buffer@1.0.4: resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} engines: {node: '>= 0.4'} @@ -7463,26 +7420,14 @@ packages: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - is-string@1.1.0: - resolution: {integrity: sha512-PlfzajuF9vSo5wErv3MJAKD/nqf9ngAs1NFQYm16nUYFO2IzxJ2hcm+IOCg+EEopdykNNUhVq5cz35cAUxU8+g==} - engines: {node: '>= 0.4'} - is-string@1.1.1: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} - is-symbol@1.1.0: - resolution: {integrity: sha512-qS8KkNNXUZ/I+nX6QT8ZS1/Yx0A444yhzdTKxCzKkNjQ9sHErBxJnJAgh+f5YhusYECEcjo4XcyH87hn6+ks0A==} - engines: {node: '>= 0.4'} - is-symbol@1.1.1: resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} - is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - is-typed-array@1.1.15: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} @@ -7499,9 +7444,6 @@ packages: resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} engines: {node: '>= 0.4'} - is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - is-weakref@1.1.1: resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} engines: {node: '>= 0.4'} @@ -7785,8 +7727,8 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true - jsdom@25.0.1: - resolution: {integrity: sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==} + jsdom@25.0.0: + resolution: {integrity: sha512-OhoFVT59T7aEq75TVw9xxEfkXgacpqAhQaYgP9y/fDqWQCMB/b1H66RfmPm/MaeaAIU9nDwMOVTlPN51+ao6CQ==} engines: {node: '>=18'} peerDependencies: canvas: ^2.11.2 @@ -8555,10 +8497,6 @@ packages: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - object.assign@4.1.7: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} @@ -8948,8 +8886,8 @@ packages: peerDependencies: postcss: ^8.2.1 - postcss@8.5.12: - resolution: {integrity: sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==} + postcss@8.5.14: + resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} postgres-array@2.0.0: @@ -9095,6 +9033,9 @@ packages: prr@1.0.1: resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + pump@3.0.3: resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} @@ -9124,6 +9065,9 @@ packages: query-selector-shadow-dom@1.0.1: resolution: {integrity: sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==} + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} @@ -9324,10 +9268,6 @@ packages: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} - reflect.getprototypeof@1.0.7: - resolution: {integrity: sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==} - engines: {node: '>= 0.4'} - regenerate-unicode-properties@10.1.1: resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} engines: {node: '>=4'} @@ -9338,10 +9278,6 @@ packages: regenerator-transform@0.15.2: resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - regexp.prototype.flags@1.5.3: - resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==} - engines: {node: '>= 0.4'} - regexp.prototype.flags@1.5.4: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} @@ -9365,6 +9301,9 @@ packages: require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -9446,10 +9385,6 @@ packages: rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} - safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - safe-array-concat@1.1.3: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} @@ -9464,10 +9399,6 @@ packages: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} - safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - safe-regex-test@1.1.0: resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} engines: {node: '>= 0.4'} @@ -9710,13 +9641,6 @@ packages: resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} - string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - string.prototype.trimend@1.0.9: resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} engines: {node: '>= 0.4'} @@ -9920,6 +9844,10 @@ packages: resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==} engines: {node: '>=14.16'} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -10046,26 +9974,14 @@ packages: resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==} engines: {node: '>= 0.6'} - typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} - typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - typed-array-byte-length@1.0.3: resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.3: - resolution: {integrity: sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==} - engines: {node: '>= 0.4'} - typed-array-byte-offset@1.0.4: resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} engines: {node: '>= 0.4'} @@ -10118,9 +10034,6 @@ packages: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} - unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -10154,6 +10067,10 @@ packages: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -10174,6 +10091,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + use-callback-ref@1.3.3: resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} engines: {node: '>=10'} @@ -10445,18 +10365,10 @@ packages: when-exit@2.1.5: resolution: {integrity: sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg==} - which-boxed-primitive@1.1.0: - resolution: {integrity: sha512-Ei7Miu/AXe2JJ4iNF5j/UphAgRoma4trE6PtisM09bPygb3egMH3YLW/befsWb1A1AxvNSFidOFTB18XtnIIng==} - engines: {node: '>= 0.4'} - which-boxed-primitive@1.1.1: resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} - which-builtin-type@1.2.0: - resolution: {integrity: sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==} - engines: {node: '>= 0.4'} - which-builtin-type@1.2.1: resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} engines: {node: '>= 0.4'} @@ -10468,10 +10380,6 @@ packages: which-module@2.0.1: resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} - which-typed-array@1.1.16: - resolution: {integrity: sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==} - engines: {node: '>= 0.4'} - which-typed-array@1.1.20: resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} engines: {node: '>= 0.4'} @@ -12430,6 +12338,11 @@ snapshots: '@esbuild/win32-x64@0.28.0': optional: true + '@eslint-community/eslint-utils@4.9.1(eslint@9.28.0(jiti@2.4.2))': + dependencies: + eslint: 9.28.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.4.2))': dependencies: eslint: 9.39.4(jiti@2.4.2) @@ -12437,6 +12350,14 @@ snapshots: '@eslint-community/regexpp@4.12.2': {} + '@eslint/config-array@0.20.1': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3 + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + '@eslint/config-array@0.21.2': dependencies: '@eslint/object-schema': 2.1.7 @@ -12445,10 +12366,20 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/config-helpers@0.2.3': {} + '@eslint/config-helpers@0.4.2': dependencies: '@eslint/core': 0.17.0 + '@eslint/core@0.14.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/core@0.15.2': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/core@0.17.0': dependencies: '@types/json-schema': 7.0.15 @@ -12467,10 +12398,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@eslint/js@9.28.0': {} + '@eslint/js@9.39.4': {} '@eslint/object-schema@2.1.7': {} + '@eslint/plugin-kit@0.3.5': + dependencies: + '@eslint/core': 0.15.2 + levn: 0.4.1 + '@eslint/plugin-kit@0.4.1': dependencies: '@eslint/core': 0.17.0 @@ -13065,7 +13003,7 @@ snapshots: '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/remapping@2.3.5': @@ -14985,10 +14923,10 @@ snapshots: '@tabler/icons@3.40.0': {} - '@tanstack/eslint-plugin-query@5.94.4(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3)': + '@tanstack/eslint-plugin-query@5.94.4(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3)': dependencies: - '@typescript-eslint/utils': 8.57.1(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3) - eslint: 9.39.4(jiti@2.4.2) + '@typescript-eslint/utils': 8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) + eslint: 9.28.0(jiti@2.4.2) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -15020,16 +14958,17 @@ snapshots: picocolors: 1.1.1 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.9.1': + '@testing-library/jest-dom@6.6.0': dependencies: '@adobe/css-tools': 4.4.3 aria-query: 5.3.2 + chalk: 3.0.0 css.escape: 1.5.1 dom-accessibility-api: 0.6.3 - picocolors: 1.1.1 + lodash: 4.18.1 redent: 3.0.0 - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@testing-library/react@16.1.0(@testing-library/dom@10.4.1)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.29.2 '@testing-library/dom': 10.4.1 @@ -15517,11 +15456,11 @@ snapshots: '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 8.56.10 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/eslint@8.56.10': dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/json-schema': 7.0.15 '@types/estree@1.0.8': {} @@ -15686,7 +15625,7 @@ snapshots: '@types/react@18.3.12': dependencies: '@types/prop-types': 15.7.11 - csstype: 3.1.3 + csstype: 3.2.3 '@types/send@0.17.4': dependencies: @@ -15747,6 +15686,22 @@ snapshots: dependencies: '@types/node': 25.5.0 + '@typescript-eslint/eslint-plugin@8.57.1(@typescript-eslint/parser@8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3))(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.57.1 + '@typescript-eslint/type-utils': 8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.57.1 + eslint: 9.28.0(jiti@2.4.2) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/eslint-plugin@8.57.1(@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3))(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -15763,6 +15718,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.57.1 + '@typescript-eslint/types': 8.57.1 + '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.57.1 + debug: 4.4.3 + eslint: 9.28.0(jiti@2.4.2) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@8.57.1(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.57.1 @@ -15793,6 +15760,18 @@ snapshots: dependencies: typescript: 5.9.3 + '@typescript-eslint/type-utils@8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.57.1 + '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.28.0(jiti@2.4.2) + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/type-utils@8.57.1(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.57.1 @@ -15822,6 +15801,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.28.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.57.1 + '@typescript-eslint/types': 8.57.1 + '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) + eslint: 9.28.0(jiti@2.4.2) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.57.1(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.4.2)) @@ -15922,10 +15912,10 @@ snapshots: '@vercel/oidc@3.1.0': {} - '@vitejs/plugin-react@6.0.1(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3))': + '@vitejs/plugin-react@6.0.1(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.7 - vite: 8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) '@vitest/expect@4.1.6': dependencies: @@ -15936,13 +15926,13 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.6(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3))': + '@vitest/mocker@4.1.6(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3))': dependencies: '@vitest/spy': 4.1.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) '@vitest/pretty-format@4.1.6': dependencies: @@ -16187,11 +16177,6 @@ snapshots: aria-query@5.3.2: {} - array-buffer-byte-length@1.0.1: - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - array-buffer-byte-length@1.0.2: dependencies: call-bound: 1.0.4 @@ -16199,57 +16184,46 @@ snapshots: array-includes@3.1.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.24.1 es-object-atoms: 1.1.1 get-intrinsic: 1.3.0 - is-string: 1.1.0 + is-string: 1.1.1 array-timsort@1.0.3: {} array.prototype.findlast@1.2.5: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.24.1 es-errors: 1.3.0 es-object-atoms: 1.1.1 es-shim-unscopables: 1.0.2 array.prototype.flat@1.3.2: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.24.1 es-shim-unscopables: 1.0.2 array.prototype.flatmap@1.3.3: dependencies: call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.24.1 es-shim-unscopables: 1.0.2 array.prototype.tosorted@1.1.4: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.24.1 es-errors: 1.3.0 es-shim-unscopables: 1.0.2 - arraybuffer.prototype.slice@1.0.3: - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.5 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - arraybuffer.prototype.slice@1.0.4: dependencies: array-buffer-byte-length: 1.0.2 @@ -16531,14 +16505,6 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 - call-bind@1.0.7: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.3.0 - set-function-length: 1.2.2 - call-bind@1.0.8: dependencies: call-bind-apply-helpers: 1.0.2 @@ -16565,6 +16531,11 @@ snapshots: chai@6.2.2: {} + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -16890,8 +16861,6 @@ snapshots: '@asamuzakjp/css-color': 2.8.3 rrweb-cssom: 0.8.0 - csstype@3.1.3: {} - csstype@3.2.3: {} cytoscape-cose-bilkent@4.1.0(cytoscape@3.33.1): @@ -17083,36 +17052,18 @@ snapshots: whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 - data-view-buffer@1.0.1: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 es-errors: 1.3.0 is-data-view: 1.0.2 - data-view-byte-length@1.0.1: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - data-view-byte-length@1.0.2: dependencies: call-bound: 1.0.4 es-errors: 1.3.0 is-data-view: 1.0.2 - data-view-byte-offset@1.0.0: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - data-view-byte-offset@1.0.1: dependencies: call-bound: 1.0.4 @@ -17230,7 +17181,7 @@ snapshots: dom-helpers@5.2.1: dependencies: '@babel/runtime': 7.29.2 - csstype: 3.1.3 + csstype: 3.2.3 dom-serializer@2.0.0: dependencies: @@ -17368,55 +17319,6 @@ snapshots: dependencies: is-arrayish: 0.2.1 - es-abstract@1.23.5: - dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - data-view-buffer: 1.0.1 - data-view-byte-length: 1.0.1 - data-view-byte-offset: 1.0.0 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.6 - get-intrinsic: 1.3.0 - get-symbol-description: 1.0.2 - globalthis: 1.0.4 - gopd: 1.2.0 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.1.0 - hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 - is-callable: 1.2.7 - is-data-view: 1.0.1 - is-negative-zero: 2.0.3 - is-regex: 1.2.0 - is-shared-array-buffer: 1.0.3 - is-string: 1.1.0 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.3 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.3 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.9 - string.prototype.trimend: 1.0.8 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.3 - typed-array-length: 1.0.7 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.16 - es-abstract@1.24.1: dependencies: array-buffer-byte-length: 1.0.2 @@ -17498,8 +17400,6 @@ snapshots: math-intrinsics: 1.1.0 safe-array-concat: 1.1.3 - es-module-lexer@2.0.0: {} - es-module-lexer@2.1.0: {} es-object-atoms@1.1.1: @@ -17520,8 +17420,8 @@ snapshots: es-to-primitive@1.3.0: dependencies: is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.1.0 + is-date-object: 1.1.0 + is-symbol: 1.1.1 es6-promise-pool@2.5.0: {} @@ -17599,22 +17499,22 @@ snapshots: dependencies: eslint: 9.39.4(jiti@2.4.2) - eslint-plugin-react-hooks@7.0.1(eslint@9.39.4(jiti@2.4.2)): + eslint-plugin-react-hooks@7.0.1(eslint@9.28.0(jiti@2.4.2)): dependencies: '@babel/core': 7.28.5 '@babel/parser': 7.28.5 - eslint: 9.39.4(jiti@2.4.2) + eslint: 9.28.0(jiti@2.4.2) hermes-parser: 0.25.1 zod: 4.3.6 zod-validation-error: 4.0.2(zod@4.3.6) transitivePeerDependencies: - supports-color - eslint-plugin-react-refresh@0.5.2(eslint@9.39.4(jiti@2.4.2)): + eslint-plugin-react-refresh@0.5.2(eslint@9.28.0(jiti@2.4.2)): dependencies: - eslint: 9.39.4(jiti@2.4.2) + eslint: 9.28.0(jiti@2.4.2) - eslint-plugin-react@7.37.5(eslint@9.39.4(jiti@2.4.2)): + eslint-plugin-react@7.37.5(eslint@9.28.0(jiti@2.4.2)): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -17622,7 +17522,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.3.1 - eslint: 9.39.4(jiti@2.4.2) + eslint: 9.28.0(jiti@2.4.2) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -17652,6 +17552,48 @@ snapshots: eslint-visitor-keys@5.0.1: {} + eslint@9.28.0(jiti@2.4.2): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.28.0(jiti@2.4.2)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.20.1 + '@eslint/config-helpers': 0.2.3 + '@eslint/core': 0.14.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.28.0 + '@eslint/plugin-kit': 0.3.5 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.9 + '@types/json-schema': 7.0.15 + ajv: 6.14.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.3 + optionalDependencies: + jiti: 2.4.2 + transitivePeerDependencies: + - supports-color + eslint@9.39.4(jiti@2.4.2): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.4.2)) @@ -17955,10 +17897,6 @@ snapshots: follow-redirects@1.16.0: {} - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -18027,13 +17965,6 @@ snapshots: function-bind@1.1.2: {} - function.prototype.name@1.1.6: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.5 - functions-have-names: 1.2.3 - function.prototype.name@1.1.8: dependencies: call-bind: 1.0.8 @@ -18075,12 +18006,6 @@ snapshots: get-stream@6.0.1: {} - get-symbol-description@1.0.2: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - get-symbol-description@1.1.0: dependencies: call-bound: 1.0.4 @@ -18157,8 +18082,6 @@ snapshots: dependencies: es-define-property: 1.0.1 - has-proto@1.0.3: {} - has-proto@1.2.0: dependencies: dunder-proto: 1.0.1 @@ -18306,12 +18229,6 @@ snapshots: inherits@2.0.4: {} - internal-slot@1.0.7: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -18346,11 +18263,6 @@ snapshots: ipaddr.js@2.2.0: {} - is-array-buffer@3.0.4: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.3.0 - is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -18371,11 +18283,6 @@ snapshots: dependencies: binary-extensions: 2.3.0 - is-boolean-object@1.2.0: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - is-boolean-object@1.2.2: dependencies: call-bound: 1.0.4 @@ -18387,20 +18294,12 @@ snapshots: dependencies: hasown: 2.0.2 - is-data-view@1.0.1: - dependencies: - is-typed-array: 1.1.13 - is-data-view@1.0.2: dependencies: call-bound: 1.0.4 get-intrinsic: 1.3.0 is-typed-array: 1.1.15 - is-date-object@1.0.5: - dependencies: - has-tostringtag: 1.0.2 - is-date-object@1.1.0: dependencies: call-bound: 1.0.4 @@ -18432,11 +18331,6 @@ snapshots: is-negative-zero@2.0.3: {} - is-number-object@1.1.0: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - is-number-object@1.1.1: dependencies: call-bound: 1.0.4 @@ -18448,13 +18342,6 @@ snapshots: is-promise@4.0.0: {} - is-regex@1.2.0: - dependencies: - call-bind: 1.0.7 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -18464,42 +18351,23 @@ snapshots: is-set@2.0.3: {} - is-shared-array-buffer@1.0.3: - dependencies: - call-bind: 1.0.7 - is-shared-array-buffer@1.0.4: dependencies: call-bound: 1.0.4 is-stream@2.0.1: {} - is-string@1.1.0: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - is-string@1.1.1: dependencies: call-bound: 1.0.4 has-tostringtag: 1.0.2 - is-symbol@1.1.0: - dependencies: - call-bind: 1.0.7 - has-symbols: 1.1.0 - safe-regex-test: 1.0.3 - is-symbol@1.1.1: dependencies: call-bound: 1.0.4 has-symbols: 1.1.0 safe-regex-test: 1.1.0 - is-typed-array@1.1.13: - dependencies: - which-typed-array: 1.1.16 - is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.20 @@ -18510,10 +18378,6 @@ snapshots: is-weakmap@2.0.2: {} - is-weakref@1.0.2: - dependencies: - call-bind: 1.0.7 - is-weakref@1.1.1: dependencies: call-bound: 1.0.4 @@ -18990,7 +18854,7 @@ snapshots: dependencies: argparse: 2.0.1 - jsdom@25.0.1: + jsdom@25.0.0: dependencies: cssstyle: 4.2.1 data-urls: 5.0.0 @@ -19005,7 +18869,7 @@ snapshots: rrweb-cssom: 0.7.1 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 5.1.2 + tough-cookie: 4.1.4 w3c-xmlserializer: 5.0.0 webidl-conversions: 7.0.0 whatwg-encoding: 3.1.1 @@ -19098,7 +18962,7 @@ snapshots: dependencies: array-includes: 3.1.8 array.prototype.flat: 1.3.2 - object.assign: 4.1.5 + object.assign: 4.1.7 object.values: 1.2.1 jszip@3.10.1: @@ -19729,13 +19593,6 @@ snapshots: object-keys@1.1.1: {} - object.assign@4.1.5: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - object.assign@4.1.7: dependencies: call-bind: 1.0.8 @@ -19754,9 +19611,9 @@ snapshots: object.fromentries@2.0.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.24.1 es-object-atoms: 1.1.1 object.values@1.2.1: @@ -20134,40 +19991,40 @@ snapshots: possible-typed-array-names@1.0.0: {} - postcss-js@4.0.1(postcss@8.5.12): + postcss-js@4.0.1(postcss@8.5.14): dependencies: camelcase-css: 2.0.1 - postcss: 8.5.12 + postcss: 8.5.14 - postcss-mixins@12.1.2(postcss@8.5.12): + postcss-mixins@12.1.2(postcss@8.5.14): dependencies: - postcss: 8.5.12 - postcss-js: 4.0.1(postcss@8.5.12) - postcss-simple-vars: 7.0.1(postcss@8.5.12) - sugarss: 5.0.1(postcss@8.5.12) + postcss: 8.5.14 + postcss-js: 4.0.1(postcss@8.5.14) + postcss-simple-vars: 7.0.1(postcss@8.5.14) + sugarss: 5.0.1(postcss@8.5.14) tinyglobby: 0.2.15 - postcss-nested@7.0.2(postcss@8.5.12): + postcss-nested@7.0.2(postcss@8.5.14): dependencies: - postcss: 8.5.12 + postcss: 8.5.14 postcss-selector-parser: 7.1.1 - postcss-preset-mantine@1.18.0(postcss@8.5.12): + postcss-preset-mantine@1.18.0(postcss@8.5.14): dependencies: - postcss: 8.5.12 - postcss-mixins: 12.1.2(postcss@8.5.12) - postcss-nested: 7.0.2(postcss@8.5.12) + postcss: 8.5.14 + postcss-mixins: 12.1.2(postcss@8.5.14) + postcss-nested: 7.0.2(postcss@8.5.14) postcss-selector-parser@7.1.1: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-simple-vars@7.0.1(postcss@8.5.12): + postcss-simple-vars@7.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.12 + postcss: 8.5.14 - postcss@8.5.12: + postcss@8.5.14: dependencies: nanoid: 3.3.8 picocolors: 1.1.1 @@ -20382,6 +20239,10 @@ snapshots: prr@1.0.1: optional: true + psl@1.15.0: + dependencies: + punycode: 2.3.1 + pump@3.0.3: dependencies: end-of-stream: 1.4.4 @@ -20407,6 +20268,8 @@ snapshots: query-selector-shadow-dom@1.0.1: {} + querystringify@2.2.0: {} + quick-format-unescaped@4.0.4: {} radix-ui@1.4.3(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -20677,16 +20540,6 @@ snapshots: get-proto: 1.0.1 which-builtin-type: 1.2.1 - reflect.getprototypeof@1.0.7: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.5 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - gopd: 1.2.0 - which-builtin-type: 1.2.0 - regenerate-unicode-properties@10.1.1: dependencies: regenerate: 1.4.2 @@ -20697,13 +20550,6 @@ snapshots: dependencies: '@babel/runtime': 7.29.2 - regexp.prototype.flags@1.5.3: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - regexp.prototype.flags@1.5.4: dependencies: call-bind: 1.0.8 @@ -20732,6 +20578,8 @@ snapshots: require-main-filename@2.0.0: {} + requires-port@1.0.0: {} + resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -20832,13 +20680,6 @@ snapshots: dependencies: tslib: 2.8.1 - safe-array-concat@1.1.2: - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - isarray: 2.0.5 - safe-array-concat@1.1.3: dependencies: call-bind: 1.0.8 @@ -20856,12 +20697,6 @@ snapshots: es-errors: 1.3.0 isarray: 2.0.5 - safe-regex-test@1.0.3: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.2.0 - safe-regex-test@1.1.0: dependencies: call-bound: 1.0.4 @@ -21149,14 +20984,14 @@ snapshots: gopd: 1.2.0 has-symbols: 1.1.0 internal-slot: 1.1.0 - regexp.prototype.flags: 1.5.3 + regexp.prototype.flags: 1.5.4 set-function-name: 2.0.2 side-channel: 1.1.0 string.prototype.repeat@1.0.0: dependencies: define-properties: 1.2.1 - es-abstract: 1.23.5 + es-abstract: 1.24.1 string.prototype.trim@1.2.10: dependencies: @@ -21168,19 +21003,6 @@ snapshots: es-object-atoms: 1.1.1 has-property-descriptors: 1.0.2 - string.prototype.trim@1.2.9: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.5 - es-object-atoms: 1.1.1 - - string.prototype.trimend@1.0.8: - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - string.prototype.trimend@1.0.9: dependencies: call-bind: 1.0.8 @@ -21190,7 +21012,7 @@ snapshots: string.prototype.trimstart@1.0.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.8 define-properties: 1.2.1 es-object-atoms: 1.1.1 @@ -21239,9 +21061,9 @@ snapshots: stylis@4.3.6: {} - sugarss@5.0.1(postcss@8.5.12): + sugarss@5.0.1(postcss@8.5.14): dependencies: - postcss: 8.5.12 + postcss: 8.5.14 superagent@10.3.0: dependencies: @@ -21371,6 +21193,13 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + tough-cookie@5.1.2: dependencies: tldts: 6.1.72 @@ -21497,49 +21326,25 @@ snapshots: media-typer: 1.1.0 mime-types: 3.0.2 - typed-array-buffer@1.0.2: - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 es-errors: 1.3.0 is-typed-array: 1.1.15 - typed-array-byte-length@1.0.1: - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.2.0 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - typed-array-byte-length@1.0.3: dependencies: call-bind: 1.0.8 - for-each: 0.3.3 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 is-typed-array: 1.1.15 - typed-array-byte-offset@1.0.3: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.2.0 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - reflect.getprototypeof: 1.0.7 - typed-array-byte-offset@1.0.4: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.8 - for-each: 0.3.3 + for-each: 0.3.5 gopd: 1.2.0 has-proto: 1.2.0 is-typed-array: 1.1.15 @@ -21547,12 +21352,23 @@ snapshots: typed-array-length@1.0.7: dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 + call-bind: 1.0.8 + for-each: 0.3.5 gopd: 1.2.0 - is-typed-array: 1.1.13 + is-typed-array: 1.1.15 possible-typed-array-names: 1.0.0 - reflect.getprototypeof: 1.0.7 + reflect.getprototypeof: 1.0.10 + + typescript-eslint@8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3): + dependencies: + '@typescript-eslint/eslint-plugin': 8.57.1(@typescript-eslint/parser@8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3))(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) + '@typescript-eslint/parser': 8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.57.1(typescript@5.9.3) + '@typescript-eslint/utils': 8.57.1(eslint@9.28.0(jiti@2.4.2))(typescript@5.9.3) + eslint: 9.28.0(jiti@2.4.2) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color typescript-eslint@8.57.1(eslint@9.39.4(jiti@2.4.2))(typescript@5.9.3): dependencies: @@ -21593,13 +21409,6 @@ snapshots: uint8array-extras@1.5.0: {} - unbox-primitive@1.0.2: - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.1.0 - which-boxed-primitive: 1.1.0 - unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -21626,6 +21435,8 @@ snapshots: unicode-property-aliases-ecmascript@2.1.0: {} + universalify@0.2.0: {} + universalify@2.0.1: {} unpipe@1.0.0: {} @@ -21664,6 +21475,11 @@ snapshots: dependencies: punycode: 2.3.1 + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + use-callback-ref@1.3.3(@types/react@18.3.12)(react@18.3.1): dependencies: react: 18.3.1 @@ -21724,11 +21540,11 @@ snapshots: vary@1.1.2: {} - vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3): + vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 picomatch: 4.0.4 - postcss: 8.5.12 + postcss: 8.5.14 rolldown: 1.0.0-rc.12 tinyglobby: 0.2.15 optionalDependencies: @@ -21737,15 +21553,15 @@ snapshots: fsevents: 2.3.3 jiti: 2.4.2 less: 4.2.0 - sugarss: 5.0.1(postcss@8.5.12) + sugarss: 5.0.1(postcss@8.5.14) terser: 5.39.0 tsx: 4.21.0 yaml: 2.8.3 - vitest@4.1.6(@opentelemetry/api@1.9.0)(@types/node@22.19.1)(happy-dom@20.8.9)(jsdom@25.0.1)(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)): + vitest@4.1.6(@opentelemetry/api@1.9.0)(@types/node@22.19.1)(happy-dom@20.8.9)(jsdom@25.0.0)(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@vitest/expect': 4.1.6 - '@vitest/mocker': 4.1.6(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)) + '@vitest/mocker': 4.1.6(vite@8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3)) '@vitest/pretty-format': 4.1.6 '@vitest/runner': 4.1.6 '@vitest/snapshot': 4.1.6 @@ -21762,13 +21578,13 @@ snapshots: tinyexec: 1.1.2 tinyglobby: 0.2.15 tinyrainbow: 3.1.0 - vite: 8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.12))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) + vite: 8.0.5(@types/node@22.19.1)(esbuild@0.28.0)(jiti@2.4.2)(less@4.2.0)(sugarss@5.0.1(postcss@8.5.14))(terser@5.39.0)(tsx@4.21.0)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 '@types/node': 22.19.1 happy-dom: 20.8.9 - jsdom: 25.0.1 + jsdom: 25.0.0 transitivePeerDependencies: - msw @@ -21825,7 +21641,7 @@ snapshots: webpack@5.106.0(@swc/core@1.5.25(@swc/helpers@0.5.5)): dependencies: '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/json-schema': 7.0.15 '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 @@ -21835,7 +21651,7 @@ snapshots: browserslist: 4.28.1 chrome-trace-event: 1.0.3 enhanced-resolve: 5.20.1 - es-module-lexer: 2.0.0 + es-module-lexer: 2.1.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -21878,14 +21694,6 @@ snapshots: when-exit@2.1.5: {} - which-boxed-primitive@1.1.0: - dependencies: - is-bigint: 1.1.0 - is-boolean-object: 1.2.0 - is-number-object: 1.1.0 - is-string: 1.1.0 - is-symbol: 1.1.0 - which-boxed-primitive@1.1.1: dependencies: is-bigint: 1.1.0 @@ -21894,22 +21702,6 @@ snapshots: is-string: 1.1.1 is-symbol: 1.1.1 - which-builtin-type@1.2.0: - dependencies: - call-bind: 1.0.7 - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.2 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.1.0 - is-generator-function: 1.0.10 - is-regex: 1.2.0 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.1.0 - which-collection: 1.0.2 - which-typed-array: 1.1.16 - which-builtin-type@1.2.1: dependencies: call-bound: 1.0.4 @@ -21922,7 +21714,7 @@ snapshots: is-regex: 1.2.1 is-weakref: 1.1.1 isarray: 2.0.5 - which-boxed-primitive: 1.1.0 + which-boxed-primitive: 1.1.1 which-collection: 1.0.2 which-typed-array: 1.1.20 @@ -21935,14 +21727,6 @@ snapshots: which-module@2.0.1: {} - which-typed-array@1.1.16: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - which-typed-array@1.1.20: dependencies: available-typed-arrays: 1.0.7 From 299a9ca3c886f74ddddbed38578747e3ba463f81 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Thu, 14 May 2026 02:54:00 +0100 Subject: [PATCH 38/63] fix: bug fixes (#2201) * fix(editor): hide transclusion borders and reset spacing in read-only mode * feat(share): add full width toggle for shared pages * feat(share): support resizing sidebar on shared pages * fix: auto redirect if there is only one SSO provider. - fix tighten sso redirect - fix share tree margin * sync * package overrides --- apps/client/src/ee/components/sso-login.tsx | 69 +- apps/client/src/ee/security/sso.utils.ts | 13 +- .../src/features/auth/hooks/use-auth.ts | 2 +- .../transclusion-reference-view.tsx | 1 + .../transclusion/transclusion-view.tsx | 1 + .../transclusion/transclusion.module.css | 31 +- .../features/share/atoms/shared-page-atom.ts | 7 +- .../features/share/components/share-shell.tsx | 73 +- .../share/components/share.module.css | 24 + apps/client/src/lib/app-route.ts | 42 +- apps/client/src/pages/share/shared-page.tsx | 8 +- apps/server/package.json | 4 +- apps/server/src/ee | 2 +- package.json | 9 +- pnpm-lock.yaml | 1232 ++++++----------- 15 files changed, 696 insertions(+), 822 deletions(-) diff --git a/apps/client/src/ee/components/sso-login.tsx b/apps/client/src/ee/components/sso-login.tsx index ff739dd35..3e84f8efc 100644 --- a/apps/client/src/ee/components/sso-login.tsx +++ b/apps/client/src/ee/components/sso-login.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { useWorkspacePublicDataQuery } from "@/features/workspace/queries/workspace-query.ts"; import { Button, Divider, Stack } from "@mantine/core"; import { IconLock, IconServer } from "@tabler/icons-react"; @@ -7,15 +7,37 @@ import { buildSsoLoginUrl } from "@/ee/security/sso.utils.ts"; import { SSO_PROVIDER } from "@/ee/security/contants.ts"; import { GoogleIcon } from "@/components/icons/google-icon.tsx"; import { LdapLoginModal } from "@/ee/components/ldap-login-modal.tsx"; +import { getRedirectParam } from "@/lib/app-route.ts"; +import useCurrentUser from "@/features/user/hooks/use-current-user.ts"; + +const SSO_AUTO_ATTEMPT_KEY = "docmost:ssoAutoAttempt"; +const SSO_AUTO_ATTEMPT_TTL_MS = 5 * 60_000; + +function recentAutoAttempt(): boolean { + try { + const raw = window.sessionStorage.getItem(SSO_AUTO_ATTEMPT_KEY); + if (!raw) return false; + const ts = Number(raw); + return Number.isFinite(ts) && Date.now() - ts < SSO_AUTO_ATTEMPT_TTL_MS; + } catch { + return false; + } +} + +function markAutoAttempt(): void { + try { + window.sessionStorage.setItem(SSO_AUTO_ATTEMPT_KEY, String(Date.now())); + } catch { + /* sessionStorage unavailable (private mode, etc.) — best effort */ + } +} export default function SsoLogin() { const { data, isLoading } = useWorkspacePublicDataQuery(); + const { data: currentUser } = useCurrentUser(); const [ldapModalOpened, setLdapModalOpened] = useState(false); const [selectedLdapProvider, setSelectedLdapProvider] = useState(null); - - if (!data?.authProviders || data?.authProviders?.length === 0) { - return null; - } + const autoRedirectedRef = useRef(false); const handleSsoLogin = (provider: IAuthProvider) => { if (provider.type === SSO_PROVIDER.LDAP) { @@ -28,10 +50,47 @@ export default function SsoLogin() { providerId: provider.id, type: provider.type, workspaceId: data.id, + redirect: getRedirectParam() ?? undefined, }); } }; + // Auto-redirect when SSO is enforced and there is exactly one non-LDAP + // provider. The user has no other option, so skip the extra click. + useEffect(() => { + if (autoRedirectedRef.current) return; + if (!data?.enforceSso) return; + if (!data.authProviders || data.authProviders.length !== 1) return; + const onlyProvider = data.authProviders[0]; + if (onlyProvider.type === SSO_PROVIDER.LDAP) return; + + // Already signed in: let useRedirectIfAuthenticated handle navigation + // instead of racing it through the IdP. + if (currentUser?.user) return; + + // Explicit logout: don't immediately bounce them back to the IdP. + const params = new URLSearchParams(window.location.search); + if (params.has("logout")) return; + + // Circuit-breaker: if we already auto-redirected within the TTL, the + // user came back (likely from an IdP failure). Show the page so they + // can read errors or pick a different account. + if (recentAutoAttempt()) return; + + autoRedirectedRef.current = true; + markAutoAttempt(); + window.location.href = buildSsoLoginUrl({ + providerId: onlyProvider.id, + type: onlyProvider.type, + workspaceId: data.id, + redirect: getRedirectParam() ?? undefined, + }); + }, [data, currentUser]); + + if (!data?.authProviders || data?.authProviders?.length === 0) { + return null; + } + const getProviderIcon = (provider: IAuthProvider) => { if (provider.type === SSO_PROVIDER.GOOGLE) { return ; diff --git a/apps/client/src/ee/security/sso.utils.ts b/apps/client/src/ee/security/sso.utils.ts index 4a4665c16..bfeb7c062 100644 --- a/apps/client/src/ee/security/sso.utils.ts +++ b/apps/client/src/ee/security/sso.utils.ts @@ -18,14 +18,21 @@ export function buildSsoLoginUrl(opts: { providerId: string; type: SSO_PROVIDER; workspaceId?: string; + redirect?: string; }): string { - const { providerId, type, workspaceId } = opts; + const { providerId, type, workspaceId, redirect } = opts; const domain = getAppUrl(); + const params = new URLSearchParams(); + if (redirect) params.set("redirect", redirect); + if (type === SSO_PROVIDER.GOOGLE) { - return `${getServerAppUrl()}/api/sso/${type}/login?workspaceId=${workspaceId}`; + if (workspaceId) params.set("workspaceId", workspaceId); + return `${getServerAppUrl()}/api/sso/${type}/login?${params.toString()}`; } - return `${domain}/api/sso/${type}/${providerId}/login`; + const query = params.toString(); + const base = `${domain}/api/sso/${type}/${providerId}/login`; + return query ? `${base}?${query}` : base; } export function getGoogleSignupUrl(): string { diff --git a/apps/client/src/features/auth/hooks/use-auth.ts b/apps/client/src/features/auth/hooks/use-auth.ts index 411e04b41..970a85897 100644 --- a/apps/client/src/features/auth/hooks/use-auth.ts +++ b/apps/client/src/features/auth/hooks/use-auth.ts @@ -166,7 +166,7 @@ export default function useAuth() { const handleLogout = async () => { setCurrentUser(RESET); await logout(); - window.location.replace(APP_ROUTE.AUTH.LOGIN); + window.location.replace(`${APP_ROUTE.AUTH.LOGIN}?logout=1`); }; const handleForgotPassword = async (data: IForgotPassword) => { diff --git a/apps/client/src/features/editor/components/transclusion/transclusion-reference-view.tsx b/apps/client/src/features/editor/components/transclusion/transclusion-reference-view.tsx index 490e179b2..e50793149 100644 --- a/apps/client/src/features/editor/components/transclusion/transclusion-reference-view.tsx +++ b/apps/client/src/features/editor/components/transclusion/transclusion-reference-view.tsx @@ -35,6 +35,7 @@ export default function TransclusionReferenceView(props: NodeViewProps) { return ( 0 ? "true" : "false"} contentEditable={false} diff --git a/apps/client/src/features/editor/components/transclusion/transclusion-view.tsx b/apps/client/src/features/editor/components/transclusion/transclusion-view.tsx index c27024472..82997f5d5 100644 --- a/apps/client/src/features/editor/components/transclusion/transclusion-view.tsx +++ b/apps/client/src/features/editor/components/transclusion/transclusion-view.tsx @@ -62,6 +62,7 @@ export default function TransclusionView(props: NodeViewProps) { return ( 0 ? "true" : "false"} data-id={transclusionId ?? undefined} > diff --git a/apps/client/src/features/editor/components/transclusion/transclusion.module.css b/apps/client/src/features/editor/components/transclusion/transclusion.module.css index 2fb5f7547..4d8d321a1 100644 --- a/apps/client/src/features/editor/components/transclusion/transclusion.module.css +++ b/apps/client/src/features/editor/components/transclusion/transclusion.module.css @@ -44,8 +44,29 @@ transition: border 0.3s; } -.transclusionWrap:hover, -.transclusionWrap:focus-within { +.transclusionWrap[data-editable="false"], +.includeWrap[data-editable="false"] { + margin-left: 0; + margin-right: 0; + width: 100%; + padding: 0; +} + +/* Cancel the wrapping .react-renderer's vertical spacing in read-only mode + so the synced block sits flush with surrounding paragraphs (whose own + margins already provide the right rhythm). */ +:global(.react-renderer.node-transclusionSource):has( + .transclusionWrap[data-editable="false"] + ), +:global(.react-renderer.node-transclusionReference):has( + .includeWrap[data-editable="false"] + ) { + margin-top: 0; + margin-bottom: 0; +} + +.transclusionWrap[data-editable="true"]:hover, +.transclusionWrap[data-editable="true"]:focus-within { border: 2px solid light-dark( var(--mantine-color-orange-2), @@ -114,9 +135,9 @@ transition: border 0.3s; } -.includeWrap:hover, -.includeWrap[data-focused="true"], -.includeWrap[data-menu-open="true"] { +.includeWrap[data-editable="true"]:hover, +.includeWrap[data-editable="true"][data-focused="true"], +.includeWrap[data-editable="true"][data-menu-open="true"] { border: 2px solid light-dark( var(--mantine-color-orange-2), diff --git a/apps/client/src/features/share/atoms/shared-page-atom.ts b/apps/client/src/features/share/atoms/shared-page-atom.ts index 813f5e61b..bf8929942 100644 --- a/apps/client/src/features/share/atoms/shared-page-atom.ts +++ b/apps/client/src/features/share/atoms/shared-page-atom.ts @@ -1,6 +1,11 @@ import { atom } from "jotai"; +import { atomWithStorage } from "jotai/utils"; import { ISharedPageTree } from "@/features/share/types/share.types"; import { SharedPageTreeNode } from "@/features/share/utils"; export const sharedPageTreeAtom = atom(null); -export const sharedTreeDataAtom = atom(null); \ No newline at end of file +export const sharedTreeDataAtom = atom(null); +export const sharedPageFullWidthAtom = atomWithStorage( + "sharedPageFullWidth", + false, +); \ No newline at end of file diff --git a/apps/client/src/features/share/components/share-shell.tsx b/apps/client/src/features/share/components/share-shell.tsx index bba226fe7..1bd559258 100644 --- a/apps/client/src/features/share/components/share-shell.tsx +++ b/apps/client/src/features/share/components/share-shell.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo } from "react"; +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { ActionIcon, AppShell, @@ -14,11 +14,16 @@ import { readOnlyEditorAtom } from "@/features/editor/atoms/editor-atoms.ts"; import { ThemeToggle } from "@/components/theme-toggle.tsx"; import { useAtomValue, useSetAtom } from "jotai"; import { useAtom } from "jotai"; -import { sharedPageTreeAtom, sharedTreeDataAtom } from "@/features/share/atoms/shared-page-atom"; +import { + sharedPageFullWidthAtom, + sharedPageTreeAtom, + sharedTreeDataAtom, +} from "@/features/share/atoms/shared-page-atom"; import { buildSharedPageTree } from "@/features/share/utils"; import { desktopSidebarAtom, mobileSidebarAtom, + sidebarWidthAtom, } from "@/components/layouts/global/hooks/atoms/sidebar-atom.ts"; import SidebarToggle from "@/components/ui/sidebar-toggle-button.tsx"; import { useTranslation } from "react-i18next"; @@ -27,7 +32,7 @@ import { mobileTableOfContentAsideAtom, tableOfContentAsideAtom, } from "@/features/share/atoms/sidebar-atom.ts"; -import { IconList } from "@tabler/icons-react"; +import { IconArrowsHorizontal, IconList } from "@tabler/icons-react"; import { useToggleToc } from "@/features/share/hooks/use-toggle-toc.ts"; import classes from "./share.module.css"; import { @@ -55,6 +60,46 @@ export default function ShareShell({ const [mobileTocOpened] = useAtom(mobileTableOfContentAsideAtom); const toggleTocMobile = useToggleToc(mobileTableOfContentAsideAtom); const toggleToc = useToggleToc(tableOfContentAsideAtom); + const [fullWidth, setFullWidth] = useAtom(sharedPageFullWidthAtom); + const [sidebarWidth, setSidebarWidth] = useAtom(sidebarWidthAtom); + const [isResizing, setIsResizing] = useState(false); + const sidebarRef = useRef(null); + + const startResizing = useCallback((e: React.MouseEvent) => { + e.preventDefault(); + setIsResizing(true); + }, []); + + const stopResizing = useCallback(() => { + setIsResizing(false); + }, []); + + const resize = useCallback( + (e: MouseEvent) => { + if (!isResizing || !sidebarRef.current) return; + const newWidth = + e.clientX - sidebarRef.current.getBoundingClientRect().left; + if (newWidth < 220) { + setSidebarWidth(220); + return; + } + if (newWidth > 600) { + setSidebarWidth(600); + return; + } + setSidebarWidth(newWidth); + }, + [isResizing, setSidebarWidth], + ); + + useEffect(() => { + window.addEventListener("mousemove", resize); + window.addEventListener("mouseup", stopResizing); + return () => { + window.removeEventListener("mousemove", resize); + window.removeEventListener("mouseup", stopResizing); + }; + }, [resize, stopResizing]); const { shareId } = useParams(); const { data } = useGetSharedPageTreeQuery(shareId); @@ -81,7 +126,7 @@ export default function ShareShell({ header={{ height: 50 }} {...(data?.pageTree?.length > 1 && { navbar: { - width: 300, + width: sidebarWidth, breakpoint: "sm", collapsed: { mobile: !mobileOpened, @@ -166,6 +211,20 @@ export default function ShareShell({ + + + setFullWidth((v) => !v)} + visibleFrom="sm" + size="sm" + > + + + @@ -174,7 +233,11 @@ export default function ShareShell({ {data?.pageTree?.length > 1 && ( - + +
)} diff --git a/apps/client/src/features/share/components/share.module.css b/apps/client/src/features/share/components/share.module.css index 617768ff1..ebf1e74cb 100644 --- a/apps/client/src/features/share/components/share.module.css +++ b/apps/client/src/features/share/components/share.module.css @@ -10,6 +10,7 @@ .treeNode { text-decoration: none; user-select: none; + padding-bottom: 0; } .navbar, @@ -18,3 +19,26 @@ width: 350px; } } + +.resizeHandle { + width: 3px; + cursor: col-resize; + position: absolute; + right: 0; + top: 0; + bottom: 0; + z-index: 1; + + &:hover, + &:active { + width: 5px; + background: light-dark( + var(--mantine-color-gray-4), + var(--mantine-color-dark-5) + ); + } + + @media (max-width: $mantine-breakpoint-sm) { + display: none; + } +} diff --git a/apps/client/src/lib/app-route.ts b/apps/client/src/lib/app-route.ts index e817c0722..48c1b87d1 100644 --- a/apps/client/src/lib/app-route.ts +++ b/apps/client/src/lib/app-route.ts @@ -31,20 +31,38 @@ const APP_ROUTE = { }, }; +export function safeRedirectPath(input: unknown): string | null { + if (typeof input !== "string") return null; + if (input.length === 0 || input.length > 2048) return null; + // Reject whitespace, backslash, and any Unicode "Other" category char + // (ASCII controls, zero-width space, BOM, bidi marks, etc). + if (/[\s\\]|\p{C}/u.test(input)) return null; + if (!input.startsWith("/") || input.startsWith("//")) return null; + if (input.toLowerCase().includes("://")) return null; + if (/^\/[a-z][a-z0-9+\-.]*:/i.test(input)) return null; + try { + const resolved = new URL(input, window.location.origin); + if (resolved.origin !== window.location.origin) return null; + return resolved.pathname + resolved.search + resolved.hash; + } catch { + return null; + } +} + export function getPostLoginRedirect(): string { const params = new URLSearchParams(window.location.search); - const redirect = params.get("redirect"); - if (redirect) { - try { - const resolved = new URL(redirect, window.location.origin); - if (resolved.origin === window.location.origin) { - return resolved.pathname + resolved.search + resolved.hash; - } - } catch { - // malformed URL, fall through to default - } - } - return APP_ROUTE.HOME; + return safeRedirectPath(params.get("redirect")) ?? APP_ROUTE.HOME; +} + +/** + * Returns the `?redirect=` value from the current URL only when it is a safe + * same-origin path. Unlike {@link getPostLoginRedirect} this returns `null` + * (not `/home`) when no redirect is present, so callers can distinguish + * "user came here directly" from "user was bounced from a deep link". + */ +export function getRedirectParam(): string | null { + const params = new URLSearchParams(window.location.search); + return safeRedirectPath(params.get("redirect")); } export default APP_ROUTE; diff --git a/apps/client/src/pages/share/shared-page.tsx b/apps/client/src/pages/share/shared-page.tsx index 0db817f60..f156208e5 100644 --- a/apps/client/src/pages/share/shared-page.tsx +++ b/apps/client/src/pages/share/shared-page.tsx @@ -9,7 +9,10 @@ import { extractPageSlugId } from "@/lib"; import { Error404 } from "@/components/ui/error-404.tsx"; import ShareBranding from "@/features/share/components/share-branding.tsx"; import { useAtomValue } from "jotai"; -import { sharedTreeDataAtom } from "@/features/share/atoms/shared-page-atom.ts"; +import { + sharedPageFullWidthAtom, + sharedTreeDataAtom, +} from "@/features/share/atoms/shared-page-atom.ts"; import { isPageInTree } from "@/features/share/utils.ts"; export default function SharedPage() { @@ -23,6 +26,7 @@ export default function SharedPage() { }); const sharedTreeData = useAtomValue(sharedTreeDataAtom); + const fullWidth = useAtomValue(sharedPageFullWidthAtom); useEffect(() => { if (shareId && data) { @@ -59,7 +63,7 @@ export default function SharedPage() { )} - + =20.0.0'} - '@aws-sdk/core@3.974.7': - resolution: {integrity: sha512-YhRC90ofz5oolTJZlA8voU/oUrCB2azi8Usx51k8hhB5LpWbYQMMXKUqSqkoL0Cru+RQJgWTHpAfEDDIwfUhJw==} + '@aws-sdk/core@3.974.9': + resolution: {integrity: sha512-bXxosFunr+v/kqNb99r1NRkrVBha7CG036fRSpWGbC1A/e363XFQN6wcZMx7MYTdRr1tYwNnkrWX2xc1rT3BCQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/crc64-nvme@3.972.7': - resolution: {integrity: sha512-QUagVVBbC8gODCF6e1aV0mE2TXWB9Opz4k8EJFdNrujUVQm5R4AjJa1mpOqzwOuROBzqJU9zawzig7M96L8Ejg==} + '@aws-sdk/crc64-nvme@3.972.8': + resolution: {integrity: sha512-fVfUCL/Xh2zINYMPZvj+iBn6XWouQf0DAnjaWCI9MkmqXzL2Iy5FoQB8O7syFe6gN6AH1ecDDU58T51Ou0kFkA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-env@3.972.33': - resolution: {integrity: sha512-bJV7eViSJV6GSuuN+VIdNVPdwPsNSf75BiC2v5alPrjR/OCcqgKwSZInKbDFz9mNeizldsyf67jt6YSIiv53Cw==} + '@aws-sdk/credential-provider-env@3.972.35': + resolution: {integrity: sha512-WkFQ8BedszVomhh/Zzs8WwnE/XBmTqZjoQVB8u/4zH6kZCjouXZpPpb93gD8m0EZmzAl7dxHE/y+yDpuKzNCMw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-http@3.972.35': - resolution: {integrity: sha512-x/BQGEIdq0oI+4WxLjKmnQvT7CnF9r8ezdGt7wXwxb7ckHXQz0Zmgxt8v3Ne0JaT3R5YefmuybHX6E8EnsDXyA==} + '@aws-sdk/credential-provider-http@3.972.37': + resolution: {integrity: sha512-ylx0ZJTU+2eNcvXQ69VNR3TVSYa/ibpvdK717/NxqR9aXRMn2QRWZaiI8aa5yY/fOWZ5mknSmxGaVxxtdwv3EA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-ini@3.972.37': - resolution: {integrity: sha512-eUTpmWfd/BKsq9medhCRcu+GRAhFP2Zrn7/2jKDHHOOjCkhrMoTp/t4cEthqFoG7gE0VGp5wUxrXTdvBCmSmJg==} + '@aws-sdk/credential-provider-ini@3.972.39': + resolution: {integrity: sha512-QhRSrdkk+Gq0AFIylpiI0N6lcJqFYV9Jtr4Luz5FpYOYbjJSfyTG6iLhnK/UPIgN1Jnon8WAmSC//16XYGvwkA==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-login@3.972.37': - resolution: {integrity: sha512-Ty68y8ISSC+g5Q3D0K8uAaoINwvfaOslnNpsF/LgVUxyosYXHawcK2yV4HLXDVugiTTYLQfJfcw0ce5meAGkKw==} + '@aws-sdk/credential-provider-login@3.972.39': + resolution: {integrity: sha512-1hU0NtC04QbFIuoBuF4aQ2A97GsSE5/A0ZJpDijwexsBREIQ4KPRYl3v/FfKCPBYsaTeGjkOFx5nLhWHY24LOw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-node@3.972.38': - resolution: {integrity: sha512-BQ9XYnBDVxR2HuV5huXYQYF/PZMTsY+EnwfGnCU2cA8Zw63XpkOtPY8WqiMIZMQCrKPQQEiFURS/o9CIolRLqg==} + '@aws-sdk/credential-provider-node@3.972.40': + resolution: {integrity: sha512-ZgrQaGkpyTlVSCCsffzijVg+KgftTAWYvI5Otc36J/4jNiHb+7MmBiJIR0a5AHLvifC92PiYHt5pijP0dswd1w==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-process@3.972.33': - resolution: {integrity: sha512-yfjGksI9WQbdMObb0VeLXqzTLI+a0qXLJT9gCDiv0+X/xjPpI3mTz6a5FibrhpuEKIe0gSgvs3MaoFZy5cx4WA==} + '@aws-sdk/credential-provider-process@3.972.35': + resolution: {integrity: sha512-hNj1rAwZWT1vfz54BwH8FUWxZuqStrM25Q5LEIwn2erHPMRVAjLlpZqEbCEEqS99eEEOhdeetnS0WeNa3iYeEQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-sso@3.972.37': - resolution: {integrity: sha512-fpwE+20ntpp3i9Xb9vUuQfXLDKYHH+5I2V+ZG96SX1nBzrruhy10RXDgmN7t1etOz3c55stlA3TeQASUA451NQ==} + '@aws-sdk/credential-provider-sso@3.972.39': + resolution: {integrity: sha512-mwIPNPldyCZkvHozb6E0X/vuQLN1UCjcA6MwUf1gaO7EwghCmuNZXatq0L3zptKFvPC4Nds7+WFUkifI1XmbSw==} engines: {node: '>=20.0.0'} - '@aws-sdk/credential-provider-web-identity@3.972.37': - resolution: {integrity: sha512-aryawqyebf+3WhAFNHfF62rekFpYtVcVN7dQ89qnAWsa4n5hJst8qBG6gXC24WHtW7Nnhkf9ScYnjwo0Brn3bw==} + '@aws-sdk/credential-provider-web-identity@3.972.39': + resolution: {integrity: sha512-b9HT8CnpyPVn1hU14Q7ihjwSPlRzToYmRYJxRd5jNHEZ43lrIhoLaTT8JmfQQt5j5M8rTX1iN1X8mvu0SM1dXA==} engines: {node: '>=20.0.0'} '@aws-sdk/lib-storage@3.1040.0': @@ -1057,20 +1058,20 @@ packages: peerDependencies: '@aws-sdk/client-s3': ^3.1040.0 - '@aws-sdk/middleware-bucket-endpoint@3.972.10': - resolution: {integrity: sha512-Vbc2frZH7wXlMNd+ZZSXUEs/l1Sv8Jj4zUnIfwrYF5lwaLdXHZ9xx4U3rjUcaye3HRhFVc+E5DbBxpRAbB16BA==} + '@aws-sdk/middleware-bucket-endpoint@3.972.11': + resolution: {integrity: sha512-AhVDn+qObNacklqmBABnFa3YfVk08CzksuuecL/x+lo95dZxXuAkqJZLUsAEKQ3EiDd5E9wTUBjh0cSogmKMYA==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-expect-continue@3.972.10': - resolution: {integrity: sha512-2Yn0f1Qiq/DjxYR3wfI3LokXnjOhFM7Ssn4LTdFDIxRMCE6I32MAsVnhPX1cUZsuVA9tiZtwwhlSLAtFGxAZlQ==} + '@aws-sdk/middleware-expect-continue@3.972.11': + resolution: {integrity: sha512-xpobcctR1AHSrvkiArgTyLffn78Lt9unPMpa/yic9RKn+bOf/5M55UIM6RaPL5xKzI06/GSsTDywTWvzEAbyyw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.974.15': - resolution: {integrity: sha512-j4Zp7rA1HfhDTteICnx/tPax4N/v5wmytgguXExUGyEwQ8Ug4EBA4kjp9puFAN1UZoBVpxoiXMiuTFvjaHjeEw==} + '@aws-sdk/middleware-flexible-checksums@3.974.17': + resolution: {integrity: sha512-Js24a6sdH9SU5DI5++nlQJayCuOweiiTjnCcAsY75/JtaXF+xysDQ6nRBYx6pUPNY22viRYmdDTFZDaA9AF46g==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-host-header@3.972.10': - resolution: {integrity: sha512-IJSsIMeVQ8MMCPbuh1AbltkFhLBLXn7aejzfX5YKT/VLDHn++Dcz8886tXckE+wQssyPUhaXrJhdakO2VilRhg==} + '@aws-sdk/middleware-host-header@3.972.11': + resolution: {integrity: sha512-CBC6+tVYaOJo7QXgN1zJ4Ba2f3/Cpy4eRViYFimXW/O5Mn8hBmgXXzHu4vy4ubT80YWnp8aCFygr7dTOa14yQg==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-location-constraint@3.972.10': @@ -1081,67 +1082,63 @@ packages: resolution: {integrity: sha512-OOuGvvz1Dm20SjZo5oEBePFqxt5nf8AwkNDSyUHvD9/bfNASmstcYxFAHUowy4n6Io7mWUZ04JURZwSBvyQanQ==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-recursion-detection@3.972.11': - resolution: {integrity: sha512-+zz6f79Kj9V5qFK2P+D8Ehjnw4AhphAlCAsPjUqEcInA9umtSSKMrHbSagEeOIsDNuvVrH98bjRHcyQukTrhaQ==} + '@aws-sdk/middleware-recursion-detection@3.972.12': + resolution: {integrity: sha512-5eltYxKB4MfdQv7/VhWxRbAVQKow5dz9votRFigTYrWJHMQXwLMltlbk7KFWSZh5NDBySfmjT7Jv/DWfYCmDng==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-sdk-s3@3.972.36': - resolution: {integrity: sha512-YhPix+0x/MdQrb1Ug1GDKeS5fqylIy+naz800asX8II4jqfTk2KY2KhmmYCwZcky8YWtRQQwWCGdoqeAnip8Uw==} + '@aws-sdk/middleware-sdk-s3@3.972.38': + resolution: {integrity: sha512-Yuv3urkJtd1/b3kIURzHwihc1SV6n1t+uiXffOD2OpylZ7+4/QnO2W73yhLZzK1Z762BaqwQ3IVRqAHWzNbQ4A==} engines: {node: '>=20.0.0'} '@aws-sdk/middleware-ssec@3.972.10': resolution: {integrity: sha512-Gli9A0u8EVVb+5bFDGS/QbSVg28w/wpEidg1ggVcSj65BDTdGR6punsOcVjqdiu1i42WHWo51MCvARPIIz9juw==} engines: {node: '>=20.0.0'} - '@aws-sdk/middleware-user-agent@3.972.37': - resolution: {integrity: sha512-N1oNpdiLoVAWYD3WFBnUi3LlfoDA06ZHo4ozyjbsJNLvILzvt//0CnR8N+CZ0NWeYgVB/5V59ivixHCWCx2ALw==} + '@aws-sdk/middleware-user-agent@3.972.39': + resolution: {integrity: sha512-MlNSvNsSVlMKKWaCzA0GP1nS4Cuq3WCXUN1vmMvd+Ctztib5kmRcpmTtKx9kikN8szAc+gcdp7uqJJervV2nQg==} engines: {node: '>=20.0.0'} - '@aws-sdk/nested-clients@3.997.5': - resolution: {integrity: sha512-jGFr6DxtcMTmzOkG/a0jCZYv4BBDmeNYVeO+/memSoDkYCJu4Y58xviYmzwJfYyIVSts+X/BVjJm1uGBnwHEMg==} + '@aws-sdk/nested-clients@3.997.7': + resolution: {integrity: sha512-jT2AXOODobQfTYGC2SChMSnZ/voIcRV/LHlY1suyhY1bdgP/voKkhEg8Ci1jiGQ4lBiaso5BEAV3ZWWpPTfmYA==} engines: {node: '>=20.0.0'} - '@aws-sdk/region-config-resolver@3.972.13': - resolution: {integrity: sha512-CvJ2ZIjK/jVD/lbOpowBVElJyC1YxLTIJ13yM0AEo0t2v7swOzGjSA6lJGH+DwZXQhcjUjoYwc8bVYCX5MDr1A==} + '@aws-sdk/region-config-resolver@3.972.14': + resolution: {integrity: sha512-VuLXVmm7+lKVxqFcOItPkXhjbJ02iUfxkxheRu41SfWf6/xrZup2A2SwHZos/LeQGu3SBHeqTQht80Uo3ienPA==} engines: {node: '>=20.0.0'} '@aws-sdk/s3-request-presigner@3.1040.0': resolution: {integrity: sha512-AmesZGG/B5sDIiWahyY11fOkXSsuHc7LciE88YFURehMVSdEORo2Vzz1d2kBgmJG9oar5Vmmwf9X/w7mqb7ytg==} engines: {node: '>=20.0.0'} - '@aws-sdk/signature-v4-multi-region@3.996.24': - resolution: {integrity: sha512-amP7tLikppN940wbBFISYqiuzVmpzMS9U3mcgtmVLjX4fdWI/SNCvrXv6ZxfVzTT4cT0rPKOLhFah2xLwzREWw==} + '@aws-sdk/signature-v4-multi-region@3.996.26': + resolution: {integrity: sha512-2N62veqdMZBCwQUHsbhtnaovOFjOa5Dn3dAD1nRqFTUXR4QmirT3HZnfus/L1DS08Vm5CkoKmL0iMVt6YbqEag==} engines: {node: '>=20.0.0'} - '@aws-sdk/token-providers@3.1039.0': - resolution: {integrity: sha512-NMSFL2HwkAOoCeLCQiqoOq5pT3vVbSjww2QZTuYgYknVwhhv125PSDzZIcL5EYnlxuPWjEOdauZK+FspkZDVdw==} + '@aws-sdk/token-providers@3.1046.0': + resolution: {integrity: sha512-9je8nZt+ntB8IjhpGNayU/AkBgvq/f4aFO2bH1LSNC5JX6K8zY4LUnr/ymqunePrwq+B5OVBpL7ILjYzMFSZAw==} engines: {node: '>=20.0.0'} '@aws-sdk/types@3.973.8': resolution: {integrity: sha512-gjlAdtHMbtR9X5iIhVUvbVcy55KnznpC6bkDUWW9z915bi0ckdUr5cjf16Kp6xq0bP5HBD2xzgbL9F9Quv5vUw==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-arn-parser@3.972.3': - resolution: {integrity: sha512-HzSD8PMFrvgi2Kserxuff5VitNq2sgf3w9qxmskKDiDTThWfVteJxuCS9JXiPIPtmCrp+7N9asfIaVhBFORllA==} + '@aws-sdk/util-endpoints@3.996.9': + resolution: {integrity: sha512-ibx8Vd73rCTHekNGeXX8cpGWoBKbNAlwKHL3yjSxxttu5QnNDaSAM7/0MFYDjU31/F4lyrPoQcGirT0ew61xcg==} engines: {node: '>=20.0.0'} - '@aws-sdk/util-endpoints@3.996.8': - resolution: {integrity: sha512-oOZHcRDihk5iEe5V25NVWg45b3qEA8OpHWVdU/XQh8Zj4heVPAJqWvMphQnU7LkufmUo10EpvFPZuQMiFLJK3g==} - engines: {node: '>=20.0.0'} - - '@aws-sdk/util-format-url@3.972.10': - resolution: {integrity: sha512-DEKiHNJVtNxdyTeQspzY+15Po/kHm6sF0Cs4HV9Q2+lplB63+DrvdeiSoOSdWEWAoO2RcY1veoXVDz2tWxWCgQ==} + '@aws-sdk/util-format-url@3.972.11': + resolution: {integrity: sha512-LSzASo5djqKTUWWHhmuj9oZ6KHLaH8eUKhZLPi75imT3CcNqzkPflU9+mwl7jHP9ROsC0dSarcnpDYwyp9J/uw==} engines: {node: '>=20.0.0'} '@aws-sdk/util-locate-window@3.535.0': resolution: {integrity: sha512-PHJ3SL6d2jpcgbqdgiPxkXpu7Drc2PYViwxSIqvvMKhDwzSB1W3mMvtpzwKM4IE7zLFodZo0GKjJ9AsoXndXhA==} engines: {node: '>=14.0.0'} - '@aws-sdk/util-user-agent-browser@3.972.10': - resolution: {integrity: sha512-FAzqXvfEssGdSIz8ejatan0bOdx1qefBWKF/gWmVBXIP1HkS7v/wjjaqrAGGKvyihrXTXW00/2/1nTJtxpXz7g==} + '@aws-sdk/util-user-agent-browser@3.972.11': + resolution: {integrity: sha512-kq3RS6XQtHMrLFShbkem6h+8fxazB3jEIsbMC6aaSInOciRGE+eGAqTgJ+obO7Euo/pjM8thVqLiLISEH9X9DA==} - '@aws-sdk/util-user-agent-node@3.973.23': - resolution: {integrity: sha512-gGwq8L2Euw0aNG6Ey4EktiAo3fSCVoDy1CaBIthd+oeaKHPXUrNaApMewQ6La5Hv0lcznOtECZaNvYyc5LXXfA==} + '@aws-sdk/util-user-agent-node@3.973.25': + resolution: {integrity: sha512-066hKH/0nvV7x4ofV/iK9kz8r/qNfcR6rzuEOFqI2vQL/fcTTsDAbTw0jmXkyMzANK8ltQdALj19ns3zuOJiUw==} engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -1149,8 +1146,8 @@ packages: aws-crt: optional: true - '@aws-sdk/xml-builder@3.972.22': - resolution: {integrity: sha512-PMYKKtJd70IsSG0yHrdAbxBr+ZWBKLvzFZfD3/urxgf6hXVMzuU5M+3MJ5G67RpOmLBu1fAUN65SbWuKUCOlAA==} + '@aws-sdk/xml-builder@3.972.23': + resolution: {integrity: sha512-A0YmgYFv+hTI9c17Ntvd2hSehm9bmJfkb+ggADBwVKA8H/3+Jx94SzR2qOB9bAA9WFeDqnfz9PKKQ+D+YAKomA==} engines: {node: '>=20.0.0'} '@aws/lambda-invoke-store@0.2.3': @@ -1817,21 +1814,12 @@ packages: '@chevrotain/cst-dts-gen@11.0.3': resolution: {integrity: sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==} - '@chevrotain/cst-dts-gen@11.1.2': - resolution: {integrity: sha512-XTsjvDVB5nDZBQB8o0o/0ozNelQtn2KrUVteIHSlPd2VAV2utEb6JzyCJaJ8tGxACR4RiBNWy5uYUHX2eji88Q==} - '@chevrotain/gast@11.0.3': resolution: {integrity: sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==} - '@chevrotain/gast@11.1.2': - resolution: {integrity: sha512-Z9zfXR5jNZb1Hlsd/p+4XWeUFugrHirq36bKzPWDSIacV+GPSVXdk+ahVWZTwjhNwofAWg/sZg58fyucKSQx5g==} - '@chevrotain/regexp-to-ast@11.0.3': resolution: {integrity: sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==} - '@chevrotain/regexp-to-ast@11.1.2': - resolution: {integrity: sha512-nMU3Uj8naWer7xpZTYJdxbAs6RIv/dxYzkYU8GSwgUtcAAlzjcPfX1w+RKRcYG8POlzMeayOQ/znfwxEGo5ulw==} - '@chevrotain/types@11.0.3': resolution: {integrity: sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==} @@ -1841,9 +1829,6 @@ packages: '@chevrotain/utils@11.0.3': resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} - '@chevrotain/utils@11.1.2': - resolution: {integrity: sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA==} - '@clickhouse/client-common@1.18.2': resolution: {integrity: sha512-J0SG6q9V31ydxonglpj9xhNRsUxCsF71iEZ784yldqMYwsHixj/9xHFDgBDX3DuMiDx/kPDfXnf+pimp08wIBA==} @@ -2413,7 +2398,7 @@ packages: resolution: {integrity: sha512-TsQLe4i2gvoTtrHje625ngThGBySOgSK3Xo2XRYOdqGN1teR8+I7vchQC46uLJi8OF62YTYA3AhSpumtkhsaKQ==} engines: {node: '>=18.14.1'} peerDependencies: - hono: 4.12.14 + hono: 4.12.18 '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} @@ -2729,8 +2714,8 @@ packages: '@keyv/serialize@1.1.1': resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} - '@langchain/core@1.1.39': - resolution: {integrity: sha512-DP9c7TREy6iA7HnywstmUAsNyJNYTFpRg2yBfQ+6H0l1HnvQzei9GsQ36GeOLxgRaD3vm9K8urCcawSC7yQpCw==} + '@langchain/core@1.1.46': + resolution: {integrity: sha512-i8rDC83BpItxChCw4Lf+6tAr+k+OUcbirc5ZkrhI9ywYWmvxegUljLGOGYvtJNTbEAIFkhYIODPE5QRqyjF6sA==} engines: {node: '>=20'} '@langchain/textsplitters@1.0.1': @@ -2811,8 +2796,8 @@ packages: '@mermaid-js/parser@0.6.3': resolution: {integrity: sha512-lnjOhe7zyHjc+If7yT4zoedx2vo4sHaTmtkl1+or8BRTnCtDmcTpAjpzDSfCZrshM5bCoz0GyidzadJAH1xobA==} - '@mermaid-js/parser@1.0.1': - resolution: {integrity: sha512-opmV19kN1JsK0T6HhhokHpcVkqKpF+x2pPDKKM2ThHtZAB5F4PROopk0amuVYK5qMrIA4erzpNm8gmPNJgMDxQ==} + '@mermaid-js/parser@1.1.1': + resolution: {integrity: sha512-VuHdsYMK1bT6X2JbcAaWAhugTRvRBRyuZgd+c22swUeI9g/ntaxF7CY7dYarhZovofCbUNO0G7JesfmNtjYOCw==} '@modelcontextprotocol/sdk@1.29.0': resolution: {integrity: sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==} @@ -3280,8 +3265,8 @@ packages: '@protobufjs/base64@1.1.2': resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - '@protobufjs/codegen@2.0.4': - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + '@protobufjs/codegen@2.0.5': + resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==} '@protobufjs/eventemitter@1.1.0': resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} @@ -3292,8 +3277,8 @@ packages: '@protobufjs/float@1.0.2': resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - '@protobufjs/inquire@1.1.0': - resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + '@protobufjs/inquire@1.1.1': + resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==} '@protobufjs/path@1.1.2': resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} @@ -3301,8 +3286,8 @@ packages: '@protobufjs/pool@1.1.0': resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - '@protobufjs/utf8@1.1.0': - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@protobufjs/utf8@1.1.1': + resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==} '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -4140,217 +4125,156 @@ packages: '@slidoapp/emoji-mart@5.8.7': resolution: {integrity: sha512-zn8CBoZRFY0M0Tps0rFgcbu1nhQDmnSoD8CqkTVobI9k3MK2WHIYRp50DXhMxRoQnoct4nomrVaY9kU01ARDTQ==} - '@smithy/chunked-blob-reader-native@4.2.3': - resolution: {integrity: sha512-jA5k5Udn7Y5717L86h4EIv06wIr3xn8GM1qHRi/Nf31annXcXHJjBKvgztnbn2TxH3xWrPBfgwHsOwZf0UmQWw==} + '@smithy/config-resolver@4.5.1': + resolution: {integrity: sha512-abXk3LhODsvRHsk0ZS9ztrg/fZatTa9Z/z4pgx65YSLR+rY6kvUG/1IgcDKEUciR8MfdnkT5oPeHJTy/HhzDIQ==} engines: {node: '>=18.0.0'} - '@smithy/chunked-blob-reader@5.2.2': - resolution: {integrity: sha512-St+kVicSyayWQca+I1rGitaOEH6uKgE8IUWoYnnEX26SWdWQcL6LvMSD19Lg+vYHKdT9B2Zuu7rd3i6Wnyb/iw==} + '@smithy/core@3.24.1': + resolution: {integrity: sha512-3mT7o4qQyUWttYnVK3A0Z/u3Xha3E81tXn32Tz6vjZiUXhBrkEivpw1hBYfh84iFF9CSzkBU9Y1DJ3Q6RQ231g==} engines: {node: '>=18.0.0'} - '@smithy/config-resolver@4.4.17': - resolution: {integrity: sha512-TzDZcAnhTyAHbXVxWZo7/tEcrIeFq20IBk8So3OLOetWpR8EwY/yEqBMBFaJMeyEiREDq4NfEl+qO3OAUD+vbQ==} + '@smithy/credential-provider-imds@4.3.1': + resolution: {integrity: sha512-0S/acwHnqX4WrjXzhdiDRxsG2s9SC0cpPIK9nZ1R6UOHd+j7uL28+4bHu22urbLk2TVw3fkp6na/+fkUt/pLNQ==} engines: {node: '>=18.0.0'} - '@smithy/core@3.23.17': - resolution: {integrity: sha512-x7BlLbUFL8NWCGjMF9C+1N5cVCxcPa7g6Tv9B4A2luWx3be3oU8hQ96wIwxe/s7OhIzvoJH73HAUSg5JXVlEtQ==} + '@smithy/eventstream-serde-browser@4.3.1': + resolution: {integrity: sha512-X7MyI1fu8M84IPKk49kO4kb27Mqp6un9/0o/MsA1ngZ5OxxWKGUxPS3S/AJ9q1cPVTSGmRcbaGNfGUSsflTJkg==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.2.14': - resolution: {integrity: sha512-Au28zBN48ZAoXdooGUHemuVBrkE+Ie6RPmGNIAJsFqj33Vhb6xAgRifUydZ2aY+M+KaMAETAlKk5NC5h1G7wpg==} + '@smithy/eventstream-serde-config-resolver@4.4.1': + resolution: {integrity: sha512-JZGbSXaBk7JY8VPzsh66ksJ0nTWXbApduFDkA/pEl3aTm2EoAiUZE1Iltp6c+X1bB8kxPQW0mHDfVdYCpWTOzg==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-codec@4.2.14': - resolution: {integrity: sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw==} + '@smithy/eventstream-serde-node@4.3.1': + resolution: {integrity: sha512-6Cn4xTNVxn9PWTHSbvf8zmcDhQW8lrLE1Xq5CJgmX6wEvdjS2S0KuE79Aiznv/jx51jpFJ98OuWyE+Bt+oG1MQ==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-browser@4.2.14': - resolution: {integrity: sha512-8IelTCtTctWRbb+0Dcy+C0aICh1qa0qWXqgjcXDmMuCvPJRnv26hiDZoAau2ILOniki65mCPKqOQs/BaWvO4CQ==} + '@smithy/fetch-http-handler@5.4.1': + resolution: {integrity: sha512-r7bN6spQ+caZC8AnyvSxkRUb57zt2jhhRw3Z+2Ez8hjq6coIikDBFUUI/+CQ1xx9K6eX1Gx6wUKo4ylU66TIqw==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-config-resolver@4.3.14': - resolution: {integrity: sha512-sqHiHpYRYo3FJlaIxD1J8PhbcmJAm7IuM16mVnwSkCToD7g00IBZzKuiLNMGmftULmEUX6/UAz8/NN5uMP8bVA==} + '@smithy/hash-blob-browser@4.3.1': + resolution: {integrity: sha512-2fbltQVQYmGd0OzPv2oDMRF0pxkzeIx8cbpx2x6W3UJWGaEyUzVPxF4d0sDXZ/r2obg+RbTyhTidXWlPDsKRKw==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-node@4.2.14': - resolution: {integrity: sha512-Ht/8BuGlKfFTy0H3+8eEu0vdpwGztCnaLLXtpXNdQqiR7Hj4vFScU3T436vRAjATglOIPjJXronY+1WxxNLSiw==} + '@smithy/hash-node@4.3.1': + resolution: {integrity: sha512-u0/zo11mg7yNneoYgTkH4sXwSmcBpbl49o4UNCtQ7hYsXxynsN25KYHmXzqi7TPk5HQL5klGnpU5koOY0O+9hw==} engines: {node: '>=18.0.0'} - '@smithy/eventstream-serde-universal@4.2.14': - resolution: {integrity: sha512-lWyt4T2XQZUZgK3tQ3Wn0w3XBvZsK/vjTuJl6bXbnGZBHH0ZUSONTYiK9TgjTTzU54xQr3DRFwpjmhp0oLm3gg==} + '@smithy/hash-stream-node@4.3.1': + resolution: {integrity: sha512-4NOnngIoXngbJw9By3u8KXRgqt4vYATpAobNBnNWxOREP7JY3kB0bUmbBNhZ7dtZV/b4auO1eFMD4cLj9OauVg==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.3.17': - resolution: {integrity: sha512-bXOvQzaSm6MnmLaWA1elgfQcAtN4UP3vXqV97bHuoOrHQOJiLT3ds6o9eo5bqd0TJfRFpzdGnDQdW3FACiAVdw==} - engines: {node: '>=18.0.0'} - - '@smithy/hash-blob-browser@4.2.15': - resolution: {integrity: sha512-0PJ4Al3fg2nM4qKrAIxyNcApgqHAXcBkN8FeizOz69z0rb26uZ6lMESYtxegaTlXB5Hj84JfwMPavMrwDMjucA==} - engines: {node: '>=18.0.0'} - - '@smithy/hash-node@4.2.14': - resolution: {integrity: sha512-8ZBDY2DD4wr+GGjTpPtiglEsqr0lUP+KHqgZcWczFf6qeZ/YRjMIOoQWVQlmwu7EtxKTd8YXD8lblmYcpBIA1g==} - engines: {node: '>=18.0.0'} - - '@smithy/hash-stream-node@4.2.14': - resolution: {integrity: sha512-tw4GANWkZPb6+BdD4Fgucqzey2+r73Z/GRo9zklsCdwrnxxumUV83ZIaBDdudV4Ylazw3EPTiJZhpX42105ruQ==} - engines: {node: '>=18.0.0'} - - '@smithy/invalid-dependency@4.2.14': - resolution: {integrity: sha512-c21qJiTSb25xvvOp+H2TNZzPCngrvl5vIPqPB8zQ/DmJF4QWXO19x1dWfMJZ6wZuuWUPPm0gV8C0cU3+ifcWuw==} + '@smithy/invalid-dependency@4.3.1': + resolution: {integrity: sha512-cLmwtDoulyZvRepAfyV+3rx5oMvuh51dbE+6En3vGC09j3uVSRt1U4oguNu32ub3soGX0oYtBs8E7S2Q4SxTqg==} engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} engines: {node: '>=14.0.0'} - '@smithy/is-array-buffer@4.2.2': - resolution: {integrity: sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==} + '@smithy/md5-js@4.3.1': + resolution: {integrity: sha512-98NalujRdzv6ggVQNYPWpL2K57UKeUB8roIr61u6+JiHd7KUlMQ+sn/vk6IG4XxEjw2vlC7eu/xjYXshUE4XXg==} engines: {node: '>=18.0.0'} - '@smithy/md5-js@4.2.14': - resolution: {integrity: sha512-V2v0vx+h0iUSNG1Alt+GNBMSLGCrl9iVsdd+Ap67HPM9PN479x12V8LkuMoKImNZxn3MXeuyUjls+/7ZACZghA==} + '@smithy/middleware-content-length@4.3.1': + resolution: {integrity: sha512-l4BUIP+wljW/Ar+0/QcGdmElI9lalrywfzNijXMBG34Z510FRzPyrDLx/blNTZOAm0C4Mvx5t/bf760CZo1ajg==} engines: {node: '>=18.0.0'} - '@smithy/middleware-content-length@4.2.14': - resolution: {integrity: sha512-xhHq7fX4/3lv5NHxLUk3OeEvl0xZ+Ek3qIbWaCL4f9JwgDZEclPBElljaZCAItdGPQl/kSM4LPMOpy1MYgprpw==} + '@smithy/middleware-endpoint@4.5.1': + resolution: {integrity: sha512-qtqu5TS+8Y18ZDkJoiXN5AMW1G4JAg1+xytzpsUvIR5a4EUsgd5HQg12lekEHWpm2TDUmOgg+hBaHK7dvyWdkA==} engines: {node: '>=18.0.0'} - '@smithy/middleware-endpoint@4.4.32': - resolution: {integrity: sha512-ZZkgyjnJppiZbIm6Qbx92pbXYi1uzenIvGhBSCDlc7NwuAkiqSgS75j1czAD25ZLs2FjMjYy1q7gyRVWG6JA0Q==} + '@smithy/middleware-retry@4.6.1': + resolution: {integrity: sha512-eTaQhxs0rfUuAkL2MSKrH8DTO7YCeAgrdN0B2/RAeuHmXQ+x52dk5qUBsi/jtcqe5LxItgq5AG5tI6Cp8c0sow==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.5.7': - resolution: {integrity: sha512-bRt6ZImqVSeTk39Nm81K20ObIiAZ3WefY7G6+iz/0tZjs4dgRRjvRX2sgsH+zi6iDCRR/aQvQofLKxxz4rPBZg==} + '@smithy/middleware-serde@4.3.1': + resolution: {integrity: sha512-t7YtUe076zWVypVmy1rX91oKi2TFJCkpfFpfMhJFpEIRPP0iL9JxjeSyFQ+1bF45JUfDzOzslUJa150WcSrBug==} engines: {node: '>=18.0.0'} - '@smithy/middleware-serde@4.2.20': - resolution: {integrity: sha512-Lx9JMO9vArPtiChE3wbEZ5akMIDQpWQtlu90lhACQmNOXcGXRbaDywMHDzuDZ2OkZzP+9wQfZi3YJT9F67zTQQ==} + '@smithy/middleware-stack@4.3.1': + resolution: {integrity: sha512-1jKwiKZxCMQNqmp4uVPYA6r+MLGjEtH07gnOUdPgbnjuOIrl/0JY/ICdpQtFgeBsQ/Up01gnSv8GYEL0fb8yvg==} engines: {node: '>=18.0.0'} - '@smithy/middleware-stack@4.2.14': - resolution: {integrity: sha512-2dvkUKLuFdKsCRmOE4Mn63co0Djtsm+JMh0bYZQupN1pJwMeE8FmQmRLLzzEMN0dnNi7CDCYYH8F0EVwWiPBeA==} + '@smithy/node-config-provider@4.4.1': + resolution: {integrity: sha512-q7tDJEJXcaSG/8TVpu2f2l9bzxTzDM9geWmltbzsY6Hfh3yiuXXTpLIO8+zwYASPPVFaTJpdKwjSSjdoDoccgw==} engines: {node: '>=18.0.0'} - '@smithy/node-config-provider@4.3.14': - resolution: {integrity: sha512-S+gFjyo/weSVL0P1b9Ts8C/CwIfNCgUPikk3sl6QVsfE/uUuO+QsF+NsE/JkpvWqqyz1wg7HFdiaZuj5CoBMRg==} + '@smithy/node-http-handler@4.7.1': + resolution: {integrity: sha512-BdEYko85f/ldp68uH8XEyIvo810xFk6eyPH81SRggTOApYHWA+Xu7B2EzLuHbe37WVLaUA7F1fWR3/zBeme2WA==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.6.1': - resolution: {integrity: sha512-iB+orM4x3xrr57X3YaXazfKnntl0LHlZB1kcXSGzMV1Tt0+YwEjGlbjk/44qEGtBzXAz6yFDzkYTKSV6Pj2HUg==} + '@smithy/protocol-http@5.4.1': + resolution: {integrity: sha512-8irPNCQgYxcSFp1aGcnDNFkTwSA+xPUaFq9V/v1+JXWu8sKr5b3cFmg2kBTkjkvypDmGeNffuNu0x5iqw1NoAw==} engines: {node: '>=18.0.0'} - '@smithy/property-provider@4.2.14': - resolution: {integrity: sha512-WuM31CgfsnQ/10i7NYr0PyxqknD72Y5uMfUMVSniPjbEPceiTErb4eIqJQ+pdxNEAUEWrewrGjIRjVbVHsxZiQ==} + '@smithy/signature-v4@5.4.1': + resolution: {integrity: sha512-728lZZEWYWubBESrfntNslZQYDKRlJDY4dcDnYbL50+gu35pGPLblu4S0/RH/RDLF6me1M87ECHsHELGL7dA/Q==} engines: {node: '>=18.0.0'} - '@smithy/protocol-http@5.3.14': - resolution: {integrity: sha512-dN5F8kHx8RNU0r+pCwNmFZyz6ChjMkzShy/zup6MtkRmmix4vZzJdW+di7x//b1LiynIev88FM18ie+wwPcQtQ==} - engines: {node: '>=18.0.0'} - - '@smithy/querystring-builder@4.2.14': - resolution: {integrity: sha512-XYA5Z0IqTeF+5XDdh4BBmSA0HvbgVZIyv4cmOoUheDNR57K1HgBp9ukUMx3Cr3XpDHHpLBnexPE3LAtDsZkj2A==} - engines: {node: '>=18.0.0'} - - '@smithy/querystring-parser@4.2.14': - resolution: {integrity: sha512-hr+YyqBD23GVvRxGGrcc/oOeNlK3PzT5Fu4dzrDXxzS1LpFiuL2PQQqKPs87M79aW7ziMs+nvB3qdw77SqE7Lw==} - engines: {node: '>=18.0.0'} - - '@smithy/service-error-classification@4.3.1': - resolution: {integrity: sha512-aUQuDGh760ts/8MU+APjIZhlLPKhIIfqyzZaJikLEIMrdxFvxuLYD0WxWzaYWpmLbQlXDe9p7EWM3HsBe0K6Gw==} - engines: {node: '>=18.0.0'} - - '@smithy/shared-ini-file-loader@4.4.9': - resolution: {integrity: sha512-495/V2I15SHgedSJoDPD23JuSfKAp726ZI1V0wtjB07Wh7q/0tri/0e0DLefZCHgxZonrGKt/OCTpAtP1wE1kQ==} - engines: {node: '>=18.0.0'} - - '@smithy/signature-v4@5.3.14': - resolution: {integrity: sha512-1D9Y/nmlVjCeSivCbhZ7hgEpmHyY1h0GvpSZt3l0xcD9JjmjVC1CHOozS6+Gh+/ldMH8JuJ6cujObQqfayAVFA==} - engines: {node: '>=18.0.0'} - - '@smithy/smithy-client@4.12.13': - resolution: {integrity: sha512-y/Pcj1V9+qG98gyu1gvftHB7rDpdh+7kIBIggs55yGm3JdtBV8GT8IFF3a1qxZ79QnaJHX9GXzvBG6tAd+czJA==} + '@smithy/smithy-client@4.13.1': + resolution: {integrity: sha512-IcznNM8Qd9u1X3oflp12tkzyOB4HbT+sfYWlWiyEysgNzSHoWcHUUsTT4y1jjDjtVuuVVQbYks+g1kVd7u1eGQ==} engines: {node: '>=18.0.0'} '@smithy/types@4.14.1': resolution: {integrity: sha512-59b5HtSVrVR/eYNei3BUj3DCPKD/G7EtDDe7OEJE7i7FtQFugYo6MxbotS8mVJkLNVf8gYaAlEBwwtJ9HzhWSg==} engines: {node: '>=18.0.0'} - '@smithy/url-parser@4.2.14': - resolution: {integrity: sha512-p06BiBigJ8bTA3MgnOfCtDUWnAMY0YfedO/GRpmc7p+wg3KW8vbXy1xwSu5ASy0wV7rRYtlfZOIKH4XqfhjSQQ==} + '@smithy/url-parser@4.3.1': + resolution: {integrity: sha512-tuelFlF2PZR/wogFC58NIrPOv+Zna4N1+3kA161/33D1Gbwvl6Nh4WsAsW05ZyPp0O6CMGsdbb0S2b/qVjRMCw==} engines: {node: '>=18.0.0'} - '@smithy/util-base64@4.3.2': - resolution: {integrity: sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==} + '@smithy/util-base64@4.4.1': + resolution: {integrity: sha512-fTHiwW2xbiRiWzfSk4IGAr3gNZCH4fuRYqt8+IuarsP/YON35576iVdePraZ6yJlFxlCL0eMec3/F7xYqoKzlg==} engines: {node: '>=18.0.0'} - '@smithy/util-body-length-browser@4.2.2': - resolution: {integrity: sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==} + '@smithy/util-body-length-browser@4.3.1': + resolution: {integrity: sha512-1scg5t4nV3hV7CZs996/XHb80aDZ5YotH4NcvkW/w/rHj+cSz0aCIzwz8aUNKB4nCDPSHRCbrKoj+TvycYefmw==} engines: {node: '>=18.0.0'} - '@smithy/util-body-length-node@4.2.3': - resolution: {integrity: sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==} + '@smithy/util-body-length-node@4.3.1': + resolution: {integrity: sha512-VRC8MKVPKrgUYThTA7ughcKMfjW6/X92H0wXGJoda0Apw4O5xbXL0GMLz40DTWlsb5hh2iItk6+XL72uJdxYcw==} engines: {node: '>=18.0.0'} '@smithy/util-buffer-from@2.2.0': resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} engines: {node: '>=14.0.0'} - '@smithy/util-buffer-from@4.2.2': - resolution: {integrity: sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==} + '@smithy/util-defaults-mode-browser@4.4.1': + resolution: {integrity: sha512-1rA7w+LjK1WJClsffC81Z/ZtjFt22QsKhBjUYEnZsGVS2nOTfOENKBzdg4SxhdwFvBCjcbpjscUfXOPwE3UHWQ==} engines: {node: '>=18.0.0'} - '@smithy/util-config-provider@4.2.2': - resolution: {integrity: sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==} + '@smithy/util-defaults-mode-node@4.3.1': + resolution: {integrity: sha512-1fk1wfQHBenQD5NitVKOFgW0wsISYAFPIXGyStJWAeCtMyRhgHYvtJxBk2rwGWA0L5QX6oM6yeHSLKPFMk59ww==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-browser@4.3.49': - resolution: {integrity: sha512-a5bNrdiONYB/qE2BuKegvUMd/+ZDwdg4vsNuuSzYE8qs2EYAdK9CynL+Rzn29PbPiUqoz/cbpRbcLzD5lEevHw==} + '@smithy/util-endpoints@3.5.1': + resolution: {integrity: sha512-yORYzJD5zoGbSDkAACr0dIjDiSEA3X8h8lggDENl1dkKpCG0TQIoItPBqtvuJHzFFjRXumcoH+/09xIuixGyCw==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.2.54': - resolution: {integrity: sha512-g1cvrJvOnzeJgEdf7AE4luI7gp6L8weE0y9a9wQUSGtjb8QRHDbCJYuE4Sy0SD9N8RrnNPFsPltAz/OSoBR9Zw==} + '@smithy/util-middleware@4.3.1': + resolution: {integrity: sha512-SRRMDcIgVXVhVbxviBaSZbuWuVW3jD08wv4ESV0V2oiw0Mki8TPVQ5IxwD3MvSTPg52QYsRP+JoMw5WdUdeWAg==} engines: {node: '>=18.0.0'} - '@smithy/util-endpoints@3.4.2': - resolution: {integrity: sha512-a55Tr+3OKld4TTtnT+RhKOQHyPxm3j/xL4OR83WBUhLJaKDS9dnJ7arRMOp3t31dcLhApwG9bgvrRXBHlLdIkg==} + '@smithy/util-retry@4.4.1': + resolution: {integrity: sha512-qkgWgwn1xw0GoY9Ea/B6FrYSPfHA0zyOtJkokwxZuvucRf2+2lfTut6adi4e4Y7LEAaxsFG7r6i05mtDCxbHKA==} engines: {node: '>=18.0.0'} - '@smithy/util-hex-encoding@4.2.2': - resolution: {integrity: sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==} - engines: {node: '>=18.0.0'} - - '@smithy/util-middleware@4.2.14': - resolution: {integrity: sha512-1Su2vj9RYNDEv/V+2E+jXkkwGsgR7dc4sfHn9Z7ruzQHJIEni9zzw5CauvRXlFJfmgcqYP8fWa0dkh2Q2YaQyw==} - engines: {node: '>=18.0.0'} - - '@smithy/util-retry@4.3.6': - resolution: {integrity: sha512-p6/FO1n2KxMeQyna067i0uJ6TSbb165ZhnRtCpWh4Foxqbfc6oW+XITaL8QkFJj3KFnDe2URt4gOhgU06EP9ew==} - engines: {node: '>=18.0.0'} - deprecated: '@smithy/util-retry v4.3.6 contains a bug in Adaptive Retry, see https://github.com/smithy-lang/smithy-typescript/issues/1993. Upgrade to 4.3.7+' - - '@smithy/util-stream@4.5.25': - resolution: {integrity: sha512-/PFpG4k8Ze8Ei+mMKj3oiPICYekthuzePZMgZbCqMiXIHHf4n2aZ4Ps0aSRShycFTGuj/J6XldmC0x0DwednIA==} - engines: {node: '>=18.0.0'} - - '@smithy/util-uri-escape@4.2.2': - resolution: {integrity: sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==} + '@smithy/util-stream@4.6.1': + resolution: {integrity: sha512-GjZfEft0M0V3n2YM/LGkr5LeLd8gxHUIzW0rUz6VtTtlAq245GxHlJghvoPEjJHKTj255iHFAiA4IsIdK40Ueg==} engines: {node: '>=18.0.0'} '@smithy/util-utf8@2.3.0': resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} - '@smithy/util-utf8@4.2.2': - resolution: {integrity: sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==} + '@smithy/util-utf8@4.3.1': + resolution: {integrity: sha512-FtRrSnriXtOs4+J8/y9SbQ1xmN71hrOsN/YJr5PQQj5nR1l7YNkGS/TEk4gr0WN7gyrUqw8/RFaYVjI18732ZA==} engines: {node: '>=18.0.0'} - '@smithy/util-waiter@4.3.0': - resolution: {integrity: sha512-JyjYmLAfS+pdxF92o4yLgEoy0zhayKTw73FU1aofLWwLcJw7iSqIY2exGmMTrl/lmZugP5p/zxdFSippJDfKWA==} - engines: {node: '>=18.0.0'} - - '@smithy/uuid@1.1.2': - resolution: {integrity: sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==} + '@smithy/util-waiter@4.4.1': + resolution: {integrity: sha512-G/gWDykZNL0NVcd1qXkoKm45jxJECp6q53DSomM5QKMsyAMEsGksVq+HwgonqYxfFJEzzHi6ljtWKXVS1pl0/Q==} engines: {node: '>=18.0.0'} '@socket.io/component-emitter@3.1.0': @@ -5871,9 +5795,6 @@ packages: chevrotain@11.0.3: resolution: {integrity: sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==} - chevrotain@11.1.2: - resolution: {integrity: sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==} - chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -6641,6 +6562,9 @@ packages: resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} engines: {node: '>= 0.4'} + es-toolkit@1.46.1: + resolution: {integrity: sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==} + es6-promise-pool@2.5.0: resolution: {integrity: sha512-VHErXfzR/6r/+yyzPKeBvO0lgjfC5cbDCQWjWwMZWSb6YU39TGIl51OUmCfWCq4ylMdJSB8zkz2vIuIeIxXApA==} engines: {node: '>=0.10.0'} @@ -7166,8 +7090,8 @@ packages: highlightjs-sap-abap@0.3.0: resolution: {integrity: sha512-nSiUvEOCycjtFA3pHaTowrbAAk5+lciBHyoVkDsd6FTRBtW9sT2dt42o2jAKbXjZVUidtacdk+j0Y2xnd233Mw==} - hono@4.12.14: - resolution: {integrity: sha512-am5zfg3yu6sqn5yjKBNqhnTX7Cv+m00ox+7jbaKkrLMRJ4rAdldd1xPd/JzbBWspqaQv6RSTrgFN95EsfhC+7w==} + hono@4.12.18: + resolution: {integrity: sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==} engines: {node: '>=16.9.0'} hookified@1.15.1: @@ -7299,8 +7223,8 @@ packages: resolution: {integrity: sha512-HuEDBTI70aYdx1v6U97SbNx9F1+svQKBDo30o0b9fw055LMepzpOOd0Ccg9Q6tbqmBSJaMuY0fB7yw9/vjBYCA==} engines: {node: '>=12.22.0'} - ip-address@10.1.0: - resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + ip-address@10.1.1: + resolution: {integrity: sha512-1FMu8/N15Ck1BL551Jf42NYIoin2unWjLQ2Fze/DXryJRl5twqtwNHlO39qERGbIOcKYWHdgRryhOC+NG4eaLw==} engines: {node: '>= 12'} ipaddr.js@1.9.1: @@ -7891,20 +7815,16 @@ packages: postgres: optional: true - kysely@0.28.14: - resolution: {integrity: sha512-SU3lgh0rPvq7upc6vvdVrCsSMUG1h3ChvHVOY7wJ2fw4C9QEB7X3d5eyYEyULUX7UQtxZJtZXGuT6U2US72UYA==} - engines: {node: '>=20.0.0'} + kysely@0.29.0: + resolution: {integrity: sha512-LrQfPUeTW7MXbMvT62moEMnpMTuj9TO3lqjCeLKjM975PJ4Alrl/43f2tlDX7xOsNptKgH4LSNGwIbXwEkLg4g==} + engines: {node: '>=22.0.0'} langium@3.3.1: resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==} engines: {node: '>=16.0.0'} - langium@4.2.1: - resolution: {integrity: sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==} - engines: {node: '>=20.10.0', npm: '>=10.2.3'} - - langsmith@0.5.19: - resolution: {integrity: sha512-5tFoETuFMvGkbPGsINNlIE4Ab86CsPhdPOQZCGwNt/NX0h5NDKQLKOWS/G2XcRUBOQl4mCNbrayUvUTWaIRsCg==} + langsmith@0.7.0: + resolution: {integrity: sha512-iiPAGHJZ3uIHGnnLSkgcYZ4+thzhsGp5U48pWuW3ETgCRtbYzoDxYJigiQ3iWkK8ovF7Vr37tYvbI1ZE0tB+6A==} peerDependencies: '@opentelemetry/api': '*' '@opentelemetry/exporter-trace-otlp-proto': '*' @@ -8226,8 +8146,8 @@ packages: merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - mermaid@11.13.0: - resolution: {integrity: sha512-fEnci+Immw6lKMFI8sqzjlATTyjLkRa6axrEgLV2yHTfv8r+h1wjFbV6xeRtd4rUV1cS4EpR9rwp3Rci7TRWDw==} + mermaid@11.15.0: + resolution: {integrity: sha512-pTMbcf3rWdtLiYGpmoTjHEpeY8seiy6sR+9nD7LOs8KfUbHE4lOUAprTRqRAcWSQ6MQpdX+YEsxShtGsINtPtw==} methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} @@ -9018,8 +8938,8 @@ packages: prosemirror-view@1.40.0: resolution: {integrity: sha512-2G3svX0Cr1sJjkD/DYWSe3cfV5VPVTBOxI9XQEGWJDFEpsZb/gh4MV29ctv+OJx2RFX4BLt09i+6zaGM/ldkCw==} - protobufjs@7.5.5: - resolution: {integrity: sha512-3wY1AxV+VBNW8Yypfd1yQY9pXnqTAN+KwQxL8iYm3/BjKYMNg4i0owhEe26PWDOMaIrzeeF98Lqd5NGz4omiIg==} + protobufjs@7.5.6: + resolution: {integrity: sha512-M71sTMB146U3u0di3yup8iM+zv8yPRNQVr1KK4tyBitl3qFvEGucq/rGDRShD2rsJhtN02RJaJ7j5X5hmy8SJg==} engines: {node: '>=12.0.0'} proxy-addr@2.0.7: @@ -10288,9 +10208,6 @@ packages: vscode-uri@3.0.8: resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} - vscode-uri@3.1.0: - resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} - w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} @@ -10851,182 +10768,164 @@ snapshots: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.7 - '@aws-sdk/credential-provider-node': 3.972.38 - '@aws-sdk/middleware-bucket-endpoint': 3.972.10 - '@aws-sdk/middleware-expect-continue': 3.972.10 - '@aws-sdk/middleware-flexible-checksums': 3.974.15 - '@aws-sdk/middleware-host-header': 3.972.10 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/credential-provider-node': 3.972.40 + '@aws-sdk/middleware-bucket-endpoint': 3.972.11 + '@aws-sdk/middleware-expect-continue': 3.972.11 + '@aws-sdk/middleware-flexible-checksums': 3.974.17 + '@aws-sdk/middleware-host-header': 3.972.11 '@aws-sdk/middleware-location-constraint': 3.972.10 '@aws-sdk/middleware-logger': 3.972.10 - '@aws-sdk/middleware-recursion-detection': 3.972.11 - '@aws-sdk/middleware-sdk-s3': 3.972.36 + '@aws-sdk/middleware-recursion-detection': 3.972.12 + '@aws-sdk/middleware-sdk-s3': 3.972.38 '@aws-sdk/middleware-ssec': 3.972.10 - '@aws-sdk/middleware-user-agent': 3.972.37 - '@aws-sdk/region-config-resolver': 3.972.13 - '@aws-sdk/signature-v4-multi-region': 3.996.24 + '@aws-sdk/middleware-user-agent': 3.972.39 + '@aws-sdk/region-config-resolver': 3.972.14 + '@aws-sdk/signature-v4-multi-region': 3.996.26 '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-endpoints': 3.996.8 - '@aws-sdk/util-user-agent-browser': 3.972.10 - '@aws-sdk/util-user-agent-node': 3.973.23 - '@smithy/config-resolver': 4.4.17 - '@smithy/core': 3.23.17 - '@smithy/eventstream-serde-browser': 4.2.14 - '@smithy/eventstream-serde-config-resolver': 4.3.14 - '@smithy/eventstream-serde-node': 4.2.14 - '@smithy/fetch-http-handler': 5.3.17 - '@smithy/hash-blob-browser': 4.2.15 - '@smithy/hash-node': 4.2.14 - '@smithy/hash-stream-node': 4.2.14 - '@smithy/invalid-dependency': 4.2.14 - '@smithy/md5-js': 4.2.14 - '@smithy/middleware-content-length': 4.2.14 - '@smithy/middleware-endpoint': 4.4.32 - '@smithy/middleware-retry': 4.5.7 - '@smithy/middleware-serde': 4.2.20 - '@smithy/middleware-stack': 4.2.14 - '@smithy/node-config-provider': 4.3.14 - '@smithy/node-http-handler': 4.6.1 - '@smithy/protocol-http': 5.3.14 - '@smithy/smithy-client': 4.12.13 + '@aws-sdk/util-endpoints': 3.996.9 + '@aws-sdk/util-user-agent-browser': 3.972.11 + '@aws-sdk/util-user-agent-node': 3.973.25 + '@smithy/config-resolver': 4.5.1 + '@smithy/core': 3.24.1 + '@smithy/eventstream-serde-browser': 4.3.1 + '@smithy/eventstream-serde-config-resolver': 4.4.1 + '@smithy/eventstream-serde-node': 4.3.1 + '@smithy/fetch-http-handler': 5.4.1 + '@smithy/hash-blob-browser': 4.3.1 + '@smithy/hash-node': 4.3.1 + '@smithy/hash-stream-node': 4.3.1 + '@smithy/invalid-dependency': 4.3.1 + '@smithy/md5-js': 4.3.1 + '@smithy/middleware-content-length': 4.3.1 + '@smithy/middleware-endpoint': 4.5.1 + '@smithy/middleware-retry': 4.6.1 + '@smithy/middleware-serde': 4.3.1 + '@smithy/middleware-stack': 4.3.1 + '@smithy/node-config-provider': 4.4.1 + '@smithy/node-http-handler': 4.7.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/smithy-client': 4.13.1 '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.2.14 - '@smithy/util-base64': 4.3.2 - '@smithy/util-body-length-browser': 4.2.2 - '@smithy/util-body-length-node': 4.2.3 - '@smithy/util-defaults-mode-browser': 4.3.49 - '@smithy/util-defaults-mode-node': 4.2.54 - '@smithy/util-endpoints': 3.4.2 - '@smithy/util-middleware': 4.2.14 - '@smithy/util-retry': 4.3.6 - '@smithy/util-stream': 4.5.25 - '@smithy/util-utf8': 4.2.2 - '@smithy/util-waiter': 4.3.0 + '@smithy/url-parser': 4.3.1 + '@smithy/util-base64': 4.4.1 + '@smithy/util-body-length-browser': 4.3.1 + '@smithy/util-body-length-node': 4.3.1 + '@smithy/util-defaults-mode-browser': 4.4.1 + '@smithy/util-defaults-mode-node': 4.3.1 + '@smithy/util-endpoints': 3.5.1 + '@smithy/util-middleware': 4.3.1 + '@smithy/util-retry': 4.4.1 + '@smithy/util-stream': 4.6.1 + '@smithy/util-utf8': 4.3.1 + '@smithy/util-waiter': 4.4.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.974.7': + '@aws-sdk/core@3.974.9': dependencies: '@aws-sdk/types': 3.973.8 - '@aws-sdk/xml-builder': 3.972.22 - '@smithy/core': 3.23.17 - '@smithy/node-config-provider': 4.3.14 - '@smithy/property-provider': 4.2.14 - '@smithy/protocol-http': 5.3.14 - '@smithy/signature-v4': 5.3.14 - '@smithy/smithy-client': 4.12.13 + '@aws-sdk/xml-builder': 3.972.23 + '@smithy/core': 3.24.1 + '@smithy/signature-v4': 5.4.1 '@smithy/types': 4.14.1 - '@smithy/util-base64': 4.3.2 - '@smithy/util-middleware': 4.2.14 - '@smithy/util-retry': 4.3.6 - '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@aws-sdk/crc64-nvme@3.972.7': + '@aws-sdk/crc64-nvme@3.972.8': dependencies: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.972.33': + '@aws-sdk/credential-provider-env@3.972.35': dependencies: - '@aws-sdk/core': 3.974.7 + '@aws-sdk/core': 3.974.9 '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.2.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.972.35': + '@aws-sdk/credential-provider-http@3.972.37': dependencies: - '@aws-sdk/core': 3.974.7 + '@aws-sdk/core': 3.974.9 '@aws-sdk/types': 3.973.8 - '@smithy/fetch-http-handler': 5.3.17 - '@smithy/node-http-handler': 4.6.1 - '@smithy/property-provider': 4.2.14 - '@smithy/protocol-http': 5.3.14 - '@smithy/smithy-client': 4.12.13 + '@smithy/core': 3.24.1 + '@smithy/fetch-http-handler': 5.4.1 + '@smithy/node-http-handler': 4.7.1 '@smithy/types': 4.14.1 - '@smithy/util-stream': 4.5.25 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.972.37': + '@aws-sdk/credential-provider-ini@3.972.39': dependencies: - '@aws-sdk/core': 3.974.7 - '@aws-sdk/credential-provider-env': 3.972.33 - '@aws-sdk/credential-provider-http': 3.972.35 - '@aws-sdk/credential-provider-login': 3.972.37 - '@aws-sdk/credential-provider-process': 3.972.33 - '@aws-sdk/credential-provider-sso': 3.972.37 - '@aws-sdk/credential-provider-web-identity': 3.972.37 - '@aws-sdk/nested-clients': 3.997.5 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/credential-provider-env': 3.972.35 + '@aws-sdk/credential-provider-http': 3.972.37 + '@aws-sdk/credential-provider-login': 3.972.39 + '@aws-sdk/credential-provider-process': 3.972.35 + '@aws-sdk/credential-provider-sso': 3.972.39 + '@aws-sdk/credential-provider-web-identity': 3.972.39 + '@aws-sdk/nested-clients': 3.997.7 '@aws-sdk/types': 3.973.8 - '@smithy/credential-provider-imds': 4.2.14 - '@smithy/property-provider': 4.2.14 - '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/core': 3.24.1 + '@smithy/credential-provider-imds': 4.3.1 '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.972.37': + '@aws-sdk/credential-provider-login@3.972.39': dependencies: - '@aws-sdk/core': 3.974.7 - '@aws-sdk/nested-clients': 3.997.5 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/nested-clients': 3.997.7 '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.2.14 - '@smithy/protocol-http': 5.3.14 - '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.972.38': + '@aws-sdk/credential-provider-node@3.972.40': dependencies: - '@aws-sdk/credential-provider-env': 3.972.33 - '@aws-sdk/credential-provider-http': 3.972.35 - '@aws-sdk/credential-provider-ini': 3.972.37 - '@aws-sdk/credential-provider-process': 3.972.33 - '@aws-sdk/credential-provider-sso': 3.972.37 - '@aws-sdk/credential-provider-web-identity': 3.972.37 + '@aws-sdk/credential-provider-env': 3.972.35 + '@aws-sdk/credential-provider-http': 3.972.37 + '@aws-sdk/credential-provider-ini': 3.972.39 + '@aws-sdk/credential-provider-process': 3.972.35 + '@aws-sdk/credential-provider-sso': 3.972.39 + '@aws-sdk/credential-provider-web-identity': 3.972.39 '@aws-sdk/types': 3.973.8 - '@smithy/credential-provider-imds': 4.2.14 - '@smithy/property-provider': 4.2.14 - '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/core': 3.24.1 + '@smithy/credential-provider-imds': 4.3.1 '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.972.33': + '@aws-sdk/credential-provider-process@3.972.35': dependencies: - '@aws-sdk/core': 3.974.7 + '@aws-sdk/core': 3.974.9 '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.2.14 - '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.972.37': + '@aws-sdk/credential-provider-sso@3.972.39': dependencies: - '@aws-sdk/core': 3.974.7 - '@aws-sdk/nested-clients': 3.997.5 - '@aws-sdk/token-providers': 3.1039.0 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/nested-clients': 3.997.7 + '@aws-sdk/token-providers': 3.1046.0 '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.2.14 - '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.972.37': + '@aws-sdk/credential-provider-web-identity@3.972.39': dependencies: - '@aws-sdk/core': 3.974.7 - '@aws-sdk/nested-clients': 3.997.5 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/nested-clients': 3.997.7 '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.2.14 - '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: @@ -11035,53 +10934,46 @@ snapshots: '@aws-sdk/lib-storage@3.1040.0(@aws-sdk/client-s3@3.1040.0)': dependencies: '@aws-sdk/client-s3': 3.1040.0 - '@smithy/middleware-endpoint': 4.4.32 - '@smithy/protocol-http': 5.3.14 - '@smithy/smithy-client': 4.12.13 + '@smithy/middleware-endpoint': 4.5.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/smithy-client': 4.13.1 '@smithy/types': 4.14.1 buffer: 5.6.0 events: 3.3.0 stream-browserify: 3.0.0 tslib: 2.8.1 - '@aws-sdk/middleware-bucket-endpoint@3.972.10': + '@aws-sdk/middleware-bucket-endpoint@3.972.11': dependencies: + '@aws-sdk/core': 3.974.9 '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-arn-parser': 3.972.3 - '@smithy/node-config-provider': 4.3.14 - '@smithy/protocol-http': 5.3.14 - '@smithy/types': 4.14.1 - '@smithy/util-config-provider': 4.2.2 - tslib: 2.8.1 - - '@aws-sdk/middleware-expect-continue@3.972.10': - dependencies: - '@aws-sdk/types': 3.973.8 - '@smithy/protocol-http': 5.3.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-flexible-checksums@3.974.15': + '@aws-sdk/middleware-expect-continue@3.972.11': + dependencies: + '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.1 + '@smithy/types': 4.14.1 + tslib: 2.8.1 + + '@aws-sdk/middleware-flexible-checksums@3.974.17': dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.974.7 - '@aws-sdk/crc64-nvme': 3.972.7 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/crc64-nvme': 3.972.8 '@aws-sdk/types': 3.973.8 - '@smithy/is-array-buffer': 4.2.2 - '@smithy/node-config-provider': 4.3.14 - '@smithy/protocol-http': 5.3.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 - '@smithy/util-middleware': 4.2.14 - '@smithy/util-stream': 4.5.25 - '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 - '@aws-sdk/middleware-host-header@3.972.10': + '@aws-sdk/middleware-host-header@3.972.11': dependencies: '@aws-sdk/types': 3.973.8 - '@smithy/protocol-http': 5.3.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 @@ -11097,29 +10989,22 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.972.11': + '@aws-sdk/middleware-recursion-detection@3.972.12': dependencies: '@aws-sdk/types': 3.973.8 '@aws/lambda-invoke-store': 0.2.3 - '@smithy/protocol-http': 5.3.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.972.36': + '@aws-sdk/middleware-sdk-s3@3.972.38': dependencies: - '@aws-sdk/core': 3.974.7 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/signature-v4-multi-region': 3.996.26 '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-arn-parser': 3.972.3 - '@smithy/core': 3.23.17 - '@smithy/node-config-provider': 4.3.14 - '@smithy/protocol-http': 5.3.14 - '@smithy/signature-v4': 5.3.14 - '@smithy/smithy-client': 4.12.13 + '@smithy/core': 3.24.1 + '@smithy/signature-v4': 5.4.1 '@smithy/types': 4.14.1 - '@smithy/util-config-provider': 4.2.2 - '@smithy/util-middleware': 4.2.14 - '@smithy/util-stream': 4.5.25 - '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 '@aws-sdk/middleware-ssec@3.972.10': @@ -11128,96 +11013,70 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.972.37': + '@aws-sdk/middleware-user-agent@3.972.39': dependencies: - '@aws-sdk/core': 3.974.7 + '@aws-sdk/core': 3.974.9 '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-endpoints': 3.996.8 - '@smithy/core': 3.23.17 - '@smithy/protocol-http': 5.3.14 + '@aws-sdk/util-endpoints': 3.996.9 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 - '@smithy/util-retry': 4.3.6 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.997.5': + '@aws-sdk/nested-clients@3.997.7': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.974.7 - '@aws-sdk/middleware-host-header': 3.972.10 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/middleware-host-header': 3.972.11 '@aws-sdk/middleware-logger': 3.972.10 - '@aws-sdk/middleware-recursion-detection': 3.972.11 - '@aws-sdk/middleware-user-agent': 3.972.37 - '@aws-sdk/region-config-resolver': 3.972.13 - '@aws-sdk/signature-v4-multi-region': 3.996.24 + '@aws-sdk/middleware-recursion-detection': 3.972.12 + '@aws-sdk/middleware-user-agent': 3.972.39 + '@aws-sdk/region-config-resolver': 3.972.14 + '@aws-sdk/signature-v4-multi-region': 3.996.26 '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-endpoints': 3.996.8 - '@aws-sdk/util-user-agent-browser': 3.972.10 - '@aws-sdk/util-user-agent-node': 3.973.23 - '@smithy/config-resolver': 4.4.17 - '@smithy/core': 3.23.17 - '@smithy/fetch-http-handler': 5.3.17 - '@smithy/hash-node': 4.2.14 - '@smithy/invalid-dependency': 4.2.14 - '@smithy/middleware-content-length': 4.2.14 - '@smithy/middleware-endpoint': 4.4.32 - '@smithy/middleware-retry': 4.5.7 - '@smithy/middleware-serde': 4.2.20 - '@smithy/middleware-stack': 4.2.14 - '@smithy/node-config-provider': 4.3.14 - '@smithy/node-http-handler': 4.6.1 - '@smithy/protocol-http': 5.3.14 - '@smithy/smithy-client': 4.12.13 + '@aws-sdk/util-endpoints': 3.996.9 + '@aws-sdk/util-user-agent-browser': 3.972.11 + '@aws-sdk/util-user-agent-node': 3.973.25 + '@smithy/core': 3.24.1 + '@smithy/fetch-http-handler': 5.4.1 + '@smithy/node-http-handler': 4.7.1 '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.2.14 - '@smithy/util-base64': 4.3.2 - '@smithy/util-body-length-browser': 4.2.2 - '@smithy/util-body-length-node': 4.2.3 - '@smithy/util-defaults-mode-browser': 4.3.49 - '@smithy/util-defaults-mode-node': 4.2.54 - '@smithy/util-endpoints': 3.4.2 - '@smithy/util-middleware': 4.2.14 - '@smithy/util-retry': 4.3.6 - '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/region-config-resolver@3.972.13': + '@aws-sdk/region-config-resolver@3.972.14': dependencies: '@aws-sdk/types': 3.973.8 - '@smithy/config-resolver': 4.4.17 - '@smithy/node-config-provider': 4.3.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 '@aws-sdk/s3-request-presigner@3.1040.0': dependencies: - '@aws-sdk/signature-v4-multi-region': 3.996.24 + '@aws-sdk/signature-v4-multi-region': 3.996.26 '@aws-sdk/types': 3.973.8 - '@aws-sdk/util-format-url': 3.972.10 - '@smithy/middleware-endpoint': 4.4.32 - '@smithy/protocol-http': 5.3.14 - '@smithy/smithy-client': 4.12.13 + '@aws-sdk/util-format-url': 3.972.11 + '@smithy/middleware-endpoint': 4.5.1 + '@smithy/protocol-http': 5.4.1 + '@smithy/smithy-client': 4.13.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.996.24': + '@aws-sdk/signature-v4-multi-region@3.996.26': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.972.36 '@aws-sdk/types': 3.973.8 - '@smithy/protocol-http': 5.3.14 - '@smithy/signature-v4': 5.3.14 + '@smithy/core': 3.24.1 + '@smithy/signature-v4': 5.4.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/token-providers@3.1039.0': + '@aws-sdk/token-providers@3.1046.0': dependencies: - '@aws-sdk/core': 3.974.7 - '@aws-sdk/nested-clients': 3.997.5 + '@aws-sdk/core': 3.974.9 + '@aws-sdk/nested-clients': 3.997.7 '@aws-sdk/types': 3.973.8 - '@smithy/property-provider': 4.2.14 - '@smithy/shared-ini-file-loader': 4.4.9 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 transitivePeerDependencies: @@ -11228,46 +11087,38 @@ snapshots: '@smithy/types': 4.14.1 tslib: 2.8.1 - '@aws-sdk/util-arn-parser@3.972.3': - dependencies: - tslib: 2.8.1 - - '@aws-sdk/util-endpoints@3.996.8': + '@aws-sdk/util-endpoints@3.996.9': dependencies: '@aws-sdk/types': 3.973.8 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.2.14 - '@smithy/util-endpoints': 3.4.2 tslib: 2.8.1 - '@aws-sdk/util-format-url@3.972.10': + '@aws-sdk/util-format-url@3.972.11': dependencies: - '@aws-sdk/types': 3.973.8 - '@smithy/querystring-builder': 4.2.14 - '@smithy/types': 4.14.1 + '@aws-sdk/core': 3.974.9 tslib: 2.8.1 '@aws-sdk/util-locate-window@3.535.0': dependencies: tslib: 2.8.1 - '@aws-sdk/util-user-agent-browser@3.972.10': + '@aws-sdk/util-user-agent-browser@3.972.11': dependencies: '@aws-sdk/types': 3.973.8 '@smithy/types': 4.14.1 bowser: 2.14.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.973.23': + '@aws-sdk/util-user-agent-node@3.973.25': dependencies: - '@aws-sdk/middleware-user-agent': 3.972.37 + '@aws-sdk/middleware-user-agent': 3.972.39 '@aws-sdk/types': 3.973.8 - '@smithy/node-config-provider': 4.3.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 - '@smithy/util-config-provider': 4.2.2 tslib: 2.8.1 - '@aws-sdk/xml-builder@3.972.22': + '@aws-sdk/xml-builder@3.972.23': dependencies: '@nodable/entities': 2.1.0 '@smithy/types': 4.14.1 @@ -12090,34 +11941,19 @@ snapshots: '@chevrotain/types': 11.0.3 lodash-es: 4.18.1 - '@chevrotain/cst-dts-gen@11.1.2': - dependencies: - '@chevrotain/gast': 11.1.2 - '@chevrotain/types': 11.1.2 - lodash-es: 4.18.1 - '@chevrotain/gast@11.0.3': dependencies: '@chevrotain/types': 11.0.3 lodash-es: 4.18.1 - '@chevrotain/gast@11.1.2': - dependencies: - '@chevrotain/types': 11.1.2 - lodash-es: 4.18.1 - '@chevrotain/regexp-to-ast@11.0.3': {} - '@chevrotain/regexp-to-ast@11.1.2': {} - '@chevrotain/types@11.0.3': {} '@chevrotain/types@11.1.2': {} '@chevrotain/utils@11.0.3': {} - '@chevrotain/utils@11.1.2': {} - '@clickhouse/client-common@1.18.2': {} '@clickhouse/client@1.18.2': @@ -12476,7 +12312,7 @@ snapshots: dependencies: '@excalidraw/markdown-to-text': 0.1.2 '@mermaid-js/parser': 0.6.3 - mermaid: 11.13.0 + mermaid: 11.15.0 nanoid: 4.0.2 '@excalidraw/random-username@1.1.0': {} @@ -12618,9 +12454,9 @@ snapshots: y-prosemirror: 1.3.7(prosemirror-model@1.25.1)(prosemirror-state@1.4.3)(prosemirror-view@1.40.0)(y-protocols@1.0.6(yjs@13.6.30))(yjs@13.6.30) yjs: 13.6.30 - '@hono/node-server@1.19.13(hono@4.12.14)': + '@hono/node-server@1.19.13(hono@4.12.18)': dependencies: - hono: 4.12.14 + hono: 4.12.18 '@humanfs/core@0.19.1': {} @@ -13043,18 +12879,14 @@ snapshots: '@keyv/serialize@1.1.1': {} - '@langchain/core@1.1.39(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0)': + '@langchain/core@1.1.46(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0)': dependencies: '@cfworker/json-schema': 4.1.1 '@standard-schema/spec': 1.1.0 - ansi-styles: 5.2.0 - camelcase: 6.3.0 - decamelize: 1.2.0 js-tiktoken: 1.0.21 - langsmith: 0.5.19(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0) + langsmith: 0.7.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0) mustache: 4.2.0 p-queue: 6.6.2 - uuid: 11.1.0 zod: 4.3.6 transitivePeerDependencies: - '@opentelemetry/api' @@ -13063,9 +12895,9 @@ snapshots: - openai - ws - '@langchain/textsplitters@1.0.1(@langchain/core@1.1.39(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0))': + '@langchain/textsplitters@1.0.1(@langchain/core@1.1.46(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0))': dependencies: - '@langchain/core': 1.1.39(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0) + '@langchain/core': 1.1.46(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0) js-tiktoken: 1.0.21 '@lifeomic/attempt@3.0.3': {} @@ -13141,13 +12973,13 @@ snapshots: dependencies: langium: 3.3.1 - '@mermaid-js/parser@1.0.1': + '@mermaid-js/parser@1.1.1': dependencies: - langium: 4.2.1 + '@chevrotain/types': 11.1.2 '@modelcontextprotocol/sdk@1.29.0(@cfworker/json-schema@4.1.1)(zod@4.3.6)': dependencies: - '@hono/node-server': 1.19.13(hono@4.12.14) + '@hono/node-server': 1.19.13(hono@4.12.18) ajv: 8.18.0 ajv-formats: 3.0.1(ajv@8.18.0) content-type: 1.0.5 @@ -13157,7 +12989,7 @@ snapshots: eventsource-parser: 3.0.6 express: 5.2.1 express-rate-limit: 8.2.2(express@5.2.1) - hono: 4.12.14 + hono: 4.12.18 jose: 6.1.3 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 @@ -13585,7 +13417,7 @@ snapshots: '@opentelemetry/sdk-logs': 0.208.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-metrics': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) - protobufjs: 7.5.5 + protobufjs: 7.5.6 '@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0)': dependencies: @@ -13641,24 +13473,24 @@ snapshots: '@protobufjs/base64@1.1.2': {} - '@protobufjs/codegen@2.0.4': {} + '@protobufjs/codegen@2.0.5': {} '@protobufjs/eventemitter@1.1.0': {} '@protobufjs/fetch@1.1.0': dependencies: '@protobufjs/aspromise': 1.1.2 - '@protobufjs/inquire': 1.1.0 + '@protobufjs/inquire': 1.1.1 '@protobufjs/float@1.0.2': {} - '@protobufjs/inquire@1.1.0': {} + '@protobufjs/inquire@1.1.1': {} '@protobufjs/path@1.1.2': {} '@protobufjs/pool@1.1.0': {} - '@protobufjs/utf8@1.1.0': {} + '@protobufjs/utf8@1.1.1': {} '@radix-ui/number@1.1.1': {} @@ -14502,251 +14334,148 @@ snapshots: '@slidoapp/emoji-mart@5.8.7': {} - '@smithy/chunked-blob-reader-native@4.2.3': + '@smithy/config-resolver@4.5.1': dependencies: - '@smithy/util-base64': 4.3.2 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/chunked-blob-reader@5.2.2': - dependencies: - tslib: 2.8.1 - - '@smithy/config-resolver@4.4.17': - dependencies: - '@smithy/node-config-provider': 4.3.14 - '@smithy/types': 4.14.1 - '@smithy/util-config-provider': 4.2.2 - '@smithy/util-endpoints': 3.4.2 - '@smithy/util-middleware': 4.2.14 - tslib: 2.8.1 - - '@smithy/core@3.23.17': - dependencies: - '@smithy/protocol-http': 5.3.14 - '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.2.14 - '@smithy/util-base64': 4.3.2 - '@smithy/util-body-length-browser': 4.2.2 - '@smithy/util-middleware': 4.2.14 - '@smithy/util-stream': 4.5.25 - '@smithy/util-utf8': 4.2.2 - '@smithy/uuid': 1.1.2 - tslib: 2.8.1 - - '@smithy/credential-provider-imds@4.2.14': - dependencies: - '@smithy/node-config-provider': 4.3.14 - '@smithy/property-provider': 4.2.14 - '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.2.14 - tslib: 2.8.1 - - '@smithy/eventstream-codec@4.2.14': + '@smithy/core@3.24.1': dependencies: '@aws-crypto/crc32': 5.2.0 '@smithy/types': 4.14.1 - '@smithy/util-hex-encoding': 4.2.2 tslib: 2.8.1 - '@smithy/eventstream-serde-browser@4.2.14': + '@smithy/credential-provider-imds@4.3.1': dependencies: - '@smithy/eventstream-serde-universal': 4.2.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/eventstream-serde-config-resolver@4.3.14': + '@smithy/eventstream-serde-browser@4.3.1': dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.4.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.4.1': + dependencies: + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/eventstream-serde-node@4.2.14': + '@smithy/hash-blob-browser@4.3.1': dependencies: - '@smithy/eventstream-serde-universal': 4.2.14 - '@smithy/types': 4.14.1 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/eventstream-serde-universal@4.2.14': + '@smithy/hash-node@4.3.1': dependencies: - '@smithy/eventstream-codec': 4.2.14 - '@smithy/types': 4.14.1 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.3.17': + '@smithy/hash-stream-node@4.3.1': dependencies: - '@smithy/protocol-http': 5.3.14 - '@smithy/querystring-builder': 4.2.14 - '@smithy/types': 4.14.1 - '@smithy/util-base64': 4.3.2 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/hash-blob-browser@4.2.15': + '@smithy/invalid-dependency@4.3.1': dependencies: - '@smithy/chunked-blob-reader': 5.2.2 - '@smithy/chunked-blob-reader-native': 4.2.3 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/hash-node@4.2.14': - dependencies: - '@smithy/types': 4.14.1 - '@smithy/util-buffer-from': 4.2.2 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - - '@smithy/hash-stream-node@4.2.14': - dependencies: - '@smithy/types': 4.14.1 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - - '@smithy/invalid-dependency@4.2.14': - dependencies: - '@smithy/types': 4.14.1 + '@smithy/core': 3.24.1 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': dependencies: tslib: 2.8.1 - '@smithy/is-array-buffer@4.2.2': + '@smithy/md5-js@4.3.1': dependencies: + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/md5-js@4.2.14': + '@smithy/middleware-content-length@4.3.1': dependencies: - '@smithy/types': 4.14.1 - '@smithy/util-utf8': 4.2.2 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/middleware-content-length@4.2.14': + '@smithy/middleware-endpoint@4.5.1': dependencies: - '@smithy/protocol-http': 5.3.14 + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.6.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.3.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.4.1': + dependencies: + '@smithy/core': 3.24.1 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.7.1': + dependencies: + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/middleware-endpoint@4.4.32': + '@smithy/protocol-http@5.4.1': dependencies: - '@smithy/core': 3.23.17 - '@smithy/middleware-serde': 4.2.20 - '@smithy/node-config-provider': 4.3.14 - '@smithy/shared-ini-file-loader': 4.4.9 - '@smithy/types': 4.14.1 - '@smithy/url-parser': 4.2.14 - '@smithy/util-middleware': 4.2.14 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/middleware-retry@4.5.7': + '@smithy/signature-v4@5.4.1': dependencies: - '@smithy/core': 3.23.17 - '@smithy/node-config-provider': 4.3.14 - '@smithy/protocol-http': 5.3.14 - '@smithy/service-error-classification': 4.3.1 - '@smithy/smithy-client': 4.12.13 - '@smithy/types': 4.14.1 - '@smithy/util-middleware': 4.2.14 - '@smithy/util-retry': 4.3.6 - '@smithy/uuid': 1.1.2 - tslib: 2.8.1 - - '@smithy/middleware-serde@4.2.20': - dependencies: - '@smithy/core': 3.23.17 - '@smithy/protocol-http': 5.3.14 + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/middleware-stack@4.2.14': + '@smithy/smithy-client@4.13.1': dependencies: + '@smithy/core': 3.24.1 '@smithy/types': 4.14.1 tslib: 2.8.1 - '@smithy/node-config-provider@4.3.14': - dependencies: - '@smithy/property-provider': 4.2.14 - '@smithy/shared-ini-file-loader': 4.4.9 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/node-http-handler@4.6.1': - dependencies: - '@smithy/protocol-http': 5.3.14 - '@smithy/querystring-builder': 4.2.14 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/property-provider@4.2.14': - dependencies: - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/protocol-http@5.3.14': - dependencies: - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/querystring-builder@4.2.14': - dependencies: - '@smithy/types': 4.14.1 - '@smithy/util-uri-escape': 4.2.2 - tslib: 2.8.1 - - '@smithy/querystring-parser@4.2.14': - dependencies: - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/service-error-classification@4.3.1': - dependencies: - '@smithy/types': 4.14.1 - - '@smithy/shared-ini-file-loader@4.4.9': - dependencies: - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/signature-v4@5.3.14': - dependencies: - '@smithy/is-array-buffer': 4.2.2 - '@smithy/protocol-http': 5.3.14 - '@smithy/types': 4.14.1 - '@smithy/util-hex-encoding': 4.2.2 - '@smithy/util-middleware': 4.2.14 - '@smithy/util-uri-escape': 4.2.2 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - - '@smithy/smithy-client@4.12.13': - dependencies: - '@smithy/core': 3.23.17 - '@smithy/middleware-endpoint': 4.4.32 - '@smithy/middleware-stack': 4.2.14 - '@smithy/protocol-http': 5.3.14 - '@smithy/types': 4.14.1 - '@smithy/util-stream': 4.5.25 - tslib: 2.8.1 - '@smithy/types@4.14.1': dependencies: tslib: 2.8.1 - '@smithy/url-parser@4.2.14': + '@smithy/url-parser@4.3.1': dependencies: - '@smithy/querystring-parser': 4.2.14 - '@smithy/types': 4.14.1 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-base64@4.3.2': + '@smithy/util-base64@4.4.1': dependencies: - '@smithy/util-buffer-from': 4.2.2 - '@smithy/util-utf8': 4.2.2 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-body-length-browser@4.2.2': + '@smithy/util-body-length-browser@4.3.1': dependencies: + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-body-length-node@4.2.3': + '@smithy/util-body-length-node@4.3.1': dependencies: + '@smithy/core': 3.24.1 tslib: 2.8.1 '@smithy/util-buffer-from@2.2.0': @@ -14754,66 +14483,34 @@ snapshots: '@smithy/is-array-buffer': 2.2.0 tslib: 2.8.1 - '@smithy/util-buffer-from@4.2.2': + '@smithy/util-defaults-mode-browser@4.4.1': dependencies: - '@smithy/is-array-buffer': 4.2.2 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-config-provider@4.2.2': + '@smithy/util-defaults-mode-node@4.3.1': dependencies: + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@4.3.49': + '@smithy/util-endpoints@3.5.1': dependencies: - '@smithy/property-provider': 4.2.14 - '@smithy/smithy-client': 4.12.13 - '@smithy/types': 4.14.1 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@4.2.54': + '@smithy/util-middleware@4.3.1': dependencies: - '@smithy/config-resolver': 4.4.17 - '@smithy/credential-provider-imds': 4.2.14 - '@smithy/node-config-provider': 4.3.14 - '@smithy/property-provider': 4.2.14 - '@smithy/smithy-client': 4.12.13 - '@smithy/types': 4.14.1 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-endpoints@3.4.2': + '@smithy/util-retry@4.4.1': dependencies: - '@smithy/node-config-provider': 4.3.14 - '@smithy/types': 4.14.1 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-hex-encoding@4.2.2': - dependencies: - tslib: 2.8.1 - - '@smithy/util-middleware@4.2.14': - dependencies: - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/util-retry@4.3.6': - dependencies: - '@smithy/service-error-classification': 4.3.1 - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/util-stream@4.5.25': - dependencies: - '@smithy/fetch-http-handler': 5.3.17 - '@smithy/node-http-handler': 4.6.1 - '@smithy/types': 4.14.1 - '@smithy/util-base64': 4.3.2 - '@smithy/util-buffer-from': 4.2.2 - '@smithy/util-hex-encoding': 4.2.2 - '@smithy/util-utf8': 4.2.2 - tslib: 2.8.1 - - '@smithy/util-uri-escape@4.2.2': + '@smithy/util-stream@4.6.1': dependencies: + '@smithy/core': 3.24.1 tslib: 2.8.1 '@smithy/util-utf8@2.3.0': @@ -14821,18 +14518,14 @@ snapshots: '@smithy/util-buffer-from': 2.2.0 tslib: 2.8.1 - '@smithy/util-utf8@4.2.2': + '@smithy/util-utf8@4.3.1': dependencies: - '@smithy/util-buffer-from': 4.2.2 + '@smithy/core': 3.24.1 tslib: 2.8.1 - '@smithy/util-waiter@4.3.0': - dependencies: - '@smithy/types': 4.14.1 - tslib: 2.8.1 - - '@smithy/uuid@1.1.2': + '@smithy/util-waiter@4.4.1': dependencies: + '@smithy/core': 3.24.1 tslib: 2.8.1 '@socket.io/component-emitter@3.1.0': {} @@ -16575,11 +16268,6 @@ snapshots: chevrotain: 11.0.3 lodash-es: 4.18.1 - chevrotain-allstar@0.3.1(chevrotain@11.1.2): - dependencies: - chevrotain: 11.1.2 - lodash-es: 4.18.1 - chevrotain@11.0.3: dependencies: '@chevrotain/cst-dts-gen': 11.0.3 @@ -16589,15 +16277,6 @@ snapshots: '@chevrotain/utils': 11.0.3 lodash-es: 4.18.1 - chevrotain@11.1.2: - dependencies: - '@chevrotain/cst-dts-gen': 11.1.2 - '@chevrotain/gast': 11.1.2 - '@chevrotain/regexp-to-ast': 11.1.2 - '@chevrotain/types': 11.1.2 - '@chevrotain/utils': 11.1.2 - lodash-es: 4.18.1 - chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -17423,6 +17102,8 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 + es-toolkit@1.46.1: {} + es6-promise-pool@2.5.0: {} esbuild@0.27.4: @@ -17712,7 +17393,7 @@ snapshots: express-rate-limit@8.2.2(express@5.2.1): dependencies: express: 5.2.1 - ip-address: 10.1.0 + ip-address: 10.1.1 express@5.2.1: dependencies: @@ -18112,7 +17793,7 @@ snapshots: highlightjs-sap-abap@0.3.0: {} - hono@4.12.14: {} + hono@4.12.18: {} hookified@1.15.1: {} @@ -18257,7 +17938,7 @@ snapshots: transitivePeerDependencies: - supports-color - ip-address@10.1.0: {} + ip-address@10.1.1: {} ipaddr.js@1.9.1: {} @@ -19005,14 +18686,14 @@ snapshots: klona@2.0.6: {} - kysely-codegen@0.20.0(kysely@0.28.14)(pg@8.16.3)(typescript@5.9.3): + kysely-codegen@0.20.0(kysely@0.29.0)(pg@8.16.3)(typescript@5.9.3): dependencies: chalk: 4.1.2 cosmiconfig: 9.0.0(typescript@5.9.3) diff: 8.0.3 dotenv: 17.2.4 dotenv-expand: 12.0.3 - kysely: 0.28.14 + kysely: 0.29.0 micromatch: 4.0.8 minimist: 1.2.8 pluralize: 8.0.0 @@ -19027,13 +18708,13 @@ snapshots: '@commander-js/extra-typings': 11.1.0(commander@11.1.0) commander: 11.1.0 - kysely-postgres-js@3.0.0(kysely@0.28.14)(postgres@3.4.8): + kysely-postgres-js@3.0.0(kysely@0.29.0)(postgres@3.4.8): dependencies: - kysely: 0.28.14 + kysely: 0.29.0 optionalDependencies: postgres: 3.4.8 - kysely@0.28.14: {} + kysely@0.29.0: {} langium@3.3.1: dependencies: @@ -19043,18 +18724,9 @@ snapshots: vscode-languageserver-textdocument: 1.0.12 vscode-uri: 3.0.8 - langium@4.2.1: - dependencies: - chevrotain: 11.1.2 - chevrotain-allstar: 0.3.1(chevrotain@11.1.2) - vscode-languageserver: 9.0.1 - vscode-languageserver-textdocument: 1.0.12 - vscode-uri: 3.1.0 - - langsmith@0.5.19(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0): + langsmith@0.7.0(@opentelemetry/api@1.9.0)(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(openai@6.2.0(ws@8.20.0)(zod@4.3.6))(ws@8.20.0): dependencies: p-queue: 6.6.2 - uuid: 10.0.0 optionalDependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) @@ -19325,11 +18997,11 @@ snapshots: merge-stream@2.0.0: {} - mermaid@11.13.0: + mermaid@11.15.0: dependencies: '@braintree/sanitize-url': 7.1.2 '@iconify/utils': 3.1.0 - '@mermaid-js/parser': 1.0.1 + '@mermaid-js/parser': 1.1.1 '@types/d3': 7.4.3 '@upsetjs/venn.js': 2.0.0 cytoscape: 3.33.1 @@ -19340,14 +19012,14 @@ snapshots: dagre-d3-es: 7.0.14 dayjs: 1.11.19 dompurify: 3.4.1 + es-toolkit: 1.46.1 katex: 0.16.40 khroma: 2.1.0 - lodash-es: 4.18.1 marked: 16.4.2 roughjs: 4.6.6 stylis: 4.3.6 ts-dedent: 2.2.0 - uuid: 11.1.0 + uuid: 14.0.0 methods@1.1.2: {} @@ -19470,11 +19142,11 @@ snapshots: reflect-metadata: 0.2.2 rxjs: 7.8.2 - nestjs-kysely@3.1.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(kysely@0.28.14)(reflect-metadata@0.2.2): + nestjs-kysely@3.1.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(kysely@0.29.0)(reflect-metadata@0.2.2): dependencies: '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) - kysely: 0.28.14 + kysely: 0.29.0 reflect-metadata: 0.2.2 nestjs-pino@4.6.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2): @@ -20214,18 +19886,18 @@ snapshots: prosemirror-state: 1.4.3 prosemirror-transform: 1.10.4 - protobufjs@7.5.5: + protobufjs@7.5.6: dependencies: '@protobufjs/aspromise': 1.1.2 '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 + '@protobufjs/codegen': 2.0.5 '@protobufjs/eventemitter': 1.1.0 '@protobufjs/fetch': 1.1.0 '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 + '@protobufjs/inquire': 1.1.1 '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 + '@protobufjs/utf8': 1.1.1 '@types/node': 25.5.0 long: 5.3.2 @@ -21607,8 +21279,6 @@ snapshots: vscode-uri@3.0.8: {} - vscode-uri@3.1.0: {} - w3c-keyname@2.2.8: {} w3c-xmlserializer@5.0.0: From 3b983a27f62f0341c449773ee8372c6124bfb95d Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Thu, 14 May 2026 03:01:55 +0100 Subject: [PATCH 39/63] sync --- apps/server/package.json | 2 +- apps/server/src/ee | 2 +- pnpm-lock.yaml | 30 +++++++++++++++--------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/server/package.json b/apps/server/package.json index f3e14770d..17d763fb8 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -81,7 +81,7 @@ "ioredis": "^5.10.1", "js-tiktoken": "^1.0.21", "jsonwebtoken": "^9.0.3", - "kysely": "^0.29.0", + "kysely": "^0.28.17", "kysely-migration-cli": "^0.4.2", "kysely-postgres-js": "^3.0.0", "ldapts": "^8.1.7", diff --git a/apps/server/src/ee b/apps/server/src/ee index 71844c097..b30e92f6a 160000 --- a/apps/server/src/ee +++ b/apps/server/src/ee @@ -1 +1 @@ -Subproject commit 71844c097213ee3d861bf5b0e91eb6766b09d215 +Subproject commit b30e92f6a024b2b1106a8243e5a313122c4b0712 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 58423036b..e7980205a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -637,14 +637,14 @@ importers: specifier: ^9.0.3 version: 9.0.3 kysely: - specifier: ^0.29.0 - version: 0.29.0 + specifier: ^0.28.17 + version: 0.28.17 kysely-migration-cli: specifier: ^0.4.2 version: 0.4.2 kysely-postgres-js: specifier: ^3.0.0 - version: 3.0.0(kysely@0.29.0)(postgres@3.4.8) + version: 3.0.0(kysely@0.28.17)(postgres@3.4.8) ldapts: specifier: ^8.1.7 version: 8.1.7 @@ -668,7 +668,7 @@ importers: version: 6.2.0(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) nestjs-kysely: specifier: ^3.1.2 - version: 3.1.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(kysely@0.29.0)(reflect-metadata@0.2.2) + version: 3.1.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(kysely@0.28.17)(reflect-metadata@0.2.2) nestjs-pino: specifier: ^4.6.1 version: 4.6.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2) @@ -819,7 +819,7 @@ importers: version: 30.3.0(@types/node@25.5.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.5.25(@swc/helpers@0.5.5))(@types/node@25.5.0)(typescript@5.9.3)) kysely-codegen: specifier: ^0.20.0 - version: 0.20.0(kysely@0.29.0)(pg@8.16.3)(typescript@5.9.3) + version: 0.20.0(kysely@0.28.17)(pg@8.16.3)(typescript@5.9.3) prettier: specifier: ^3.8.1 version: 3.8.1 @@ -7815,9 +7815,9 @@ packages: postgres: optional: true - kysely@0.29.0: - resolution: {integrity: sha512-LrQfPUeTW7MXbMvT62moEMnpMTuj9TO3lqjCeLKjM975PJ4Alrl/43f2tlDX7xOsNptKgH4LSNGwIbXwEkLg4g==} - engines: {node: '>=22.0.0'} + kysely@0.28.17: + resolution: {integrity: sha512-nbD8lB9EB3wNdMhOCdx5Li8DxnLbvKByylRLcJ1h+4SkrowVeECAyZlyiKMThF7xFdRz0jSQ2MoJr+wXux2y0Q==} + engines: {node: '>=20.0.0'} langium@3.3.1: resolution: {integrity: sha512-QJv/h939gDpvT+9SiLVlY7tZC3xB2qK57v0J04Sh9wpMb6MP1q8gB21L3WIo8T5P1MSMg3Ep14L7KkDCFG3y4w==} @@ -18686,14 +18686,14 @@ snapshots: klona@2.0.6: {} - kysely-codegen@0.20.0(kysely@0.29.0)(pg@8.16.3)(typescript@5.9.3): + kysely-codegen@0.20.0(kysely@0.28.17)(pg@8.16.3)(typescript@5.9.3): dependencies: chalk: 4.1.2 cosmiconfig: 9.0.0(typescript@5.9.3) diff: 8.0.3 dotenv: 17.2.4 dotenv-expand: 12.0.3 - kysely: 0.29.0 + kysely: 0.28.17 micromatch: 4.0.8 minimist: 1.2.8 pluralize: 8.0.0 @@ -18708,13 +18708,13 @@ snapshots: '@commander-js/extra-typings': 11.1.0(commander@11.1.0) commander: 11.1.0 - kysely-postgres-js@3.0.0(kysely@0.29.0)(postgres@3.4.8): + kysely-postgres-js@3.0.0(kysely@0.28.17)(postgres@3.4.8): dependencies: - kysely: 0.29.0 + kysely: 0.28.17 optionalDependencies: postgres: 3.4.8 - kysely@0.29.0: {} + kysely@0.28.17: {} langium@3.3.1: dependencies: @@ -19142,11 +19142,11 @@ snapshots: reflect-metadata: 0.2.2 rxjs: 7.8.2 - nestjs-kysely@3.1.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(kysely@0.29.0)(reflect-metadata@0.2.2): + nestjs-kysely@3.1.2(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.19)(kysely@0.28.17)(reflect-metadata@0.2.2): dependencies: '@nestjs/common': 11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.19(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.19)(reflect-metadata@0.2.2)(rxjs@7.8.2) - kysely: 0.29.0 + kysely: 0.28.17 reflect-metadata: 0.2.2 nestjs-pino@4.6.1(@nestjs/common@11.1.19(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(pino-http@11.0.0)(pino@10.1.0)(rxjs@7.8.2): From f4af4c3fc0957f7cc7005182a09f41ccba0ec032 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Thu, 14 May 2026 03:48:13 +0100 Subject: [PATCH 40/63] feat(editor): add page break node (#2202) --- .../public/locales/en-US/translation.json | 2 + .../fixed-toolbar/groups/block-type-group.tsx | 7 +++ .../components/slash-menu/menu-items.ts | 9 +++ .../features/editor/extensions/extensions.ts | 2 + .../src/features/editor/styles/index.css | 1 + .../src/features/editor/styles/page-break.css | 50 ++++++++++++++++ .../src/collaboration/collaboration.util.ts | 2 + packages/editor-ext/src/index.ts | 1 + .../editor-ext/src/lib/page-break/index.ts | 1 + .../src/lib/page-break/page-break.ts | 60 +++++++++++++++++++ 10 files changed, 135 insertions(+) create mode 100644 apps/client/src/features/editor/styles/page-break.css create mode 100644 packages/editor-ext/src/lib/page-break/index.ts create mode 100644 packages/editor-ext/src/lib/page-break/page-break.ts diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index 268d696c8..e85f2af23 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -361,6 +361,8 @@ "Create block quote.": "Create block quote.", "Insert code snippet.": "Insert code snippet.", "Insert horizontal rule divider": "Insert horizontal rule divider", + "Page break": "Page break", + "Insert a page break for printing.": "Insert a page break for printing.", "Upload any image from your device.": "Upload any image from your device.", "Upload any video from your device.": "Upload any video from your device.", "Upload any audio from your device.": "Upload any audio from your device.", diff --git a/apps/client/src/features/editor/components/fixed-toolbar/groups/block-type-group.tsx b/apps/client/src/features/editor/components/fixed-toolbar/groups/block-type-group.tsx index 3edb28eda..69911f7cb 100644 --- a/apps/client/src/features/editor/components/fixed-toolbar/groups/block-type-group.tsx +++ b/apps/client/src/features/editor/components/fixed-toolbar/groups/block-type-group.tsx @@ -10,6 +10,7 @@ import { IconH2, IconH3, IconMenu4, + IconPageBreak, IconTypography, } from "@tabler/icons-react"; import { useTranslation } from "react-i18next"; @@ -102,6 +103,12 @@ export const BlockTypeGroup: FC = ({ editor }) => { > {t("Divider")} + } + onClick={() => editor.chain().focus().setPageBreak().run()} + > + {t("Page break")} + ); diff --git a/apps/client/src/features/editor/components/slash-menu/menu-items.ts b/apps/client/src/features/editor/components/slash-menu/menu-items.ts index 4a0532fe3..cddddc35f 100644 --- a/apps/client/src/features/editor/components/slash-menu/menu-items.ts +++ b/apps/client/src/features/editor/components/slash-menu/menu-items.ts @@ -19,6 +19,7 @@ import { IconTable, IconTypography, IconMenu4, + IconPageBreak, IconCalendar, IconAppWindow, IconSitemap, @@ -164,6 +165,14 @@ const CommandGroups: SlashMenuGroupedItemsType = { command: ({ editor, range }: CommandProps) => editor.chain().focus().deleteRange(range).setHorizontalRule().run(), }, + { + title: "Page break", + description: "Insert a page break for printing.", + searchTerms: ["page", "break", "pagebreak", "print"], + icon: IconPageBreak, + command: ({ editor, range }: CommandProps) => + editor.chain().focus().deleteRange(range).setPageBreak().run(), + }, { title: "Image", description: "Upload any image from your device.", diff --git a/apps/client/src/features/editor/extensions/extensions.ts b/apps/client/src/features/editor/extensions/extensions.ts index 1f09bef37..91411daef 100644 --- a/apps/client/src/features/editor/extensions/extensions.ts +++ b/apps/client/src/features/editor/extensions/extensions.ts @@ -42,6 +42,7 @@ import { Excalidraw, Embed, TiptapPdf, + PageBreak, SearchAndReplace, Mention, TableDndExtension, @@ -366,6 +367,7 @@ export const mainExtensions = [ TiptapPdf.configure({ view: PdfView, }), + PageBreak, Subpages.configure({ view: SubpagesView, }), diff --git a/apps/client/src/features/editor/styles/index.css b/apps/client/src/features/editor/styles/index.css index 7abfe1086..52d9268e1 100644 --- a/apps/client/src/features/editor/styles/index.css +++ b/apps/client/src/features/editor/styles/index.css @@ -9,6 +9,7 @@ @import "./media.css"; @import "./code.css"; @import "./print.css"; +@import "./page-break.css"; @import "./find.css"; @import "./mention.css"; @import "./ordered-list.css"; diff --git a/apps/client/src/features/editor/styles/page-break.css b/apps/client/src/features/editor/styles/page-break.css new file mode 100644 index 000000000..6dc97c738 --- /dev/null +++ b/apps/client/src/features/editor/styles/page-break.css @@ -0,0 +1,50 @@ +.ProseMirror .page-break { + position: relative; + margin: 1.5rem 0; + border-top: 1px dashed var(--mantine-color-default-border); + height: 0; + user-select: none; +} + +.ProseMirror[contenteditable="false"] .page-break { + margin: 0; + border: none; + height: 0; +} + +.ProseMirror[contenteditable="false"] .page-break::after { + content: none; +} + +.ProseMirror .page-break::after { + content: "Page break"; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 0 0.5rem; + background: var(--mantine-color-body); + color: var(--mantine-color-dimmed); + font-size: 0.75rem; + line-height: 1; + letter-spacing: 0.02em; + text-transform: uppercase; +} + +.ProseMirror .page-break.ProseMirror-selectednode { + border-top-color: var(--mantine-primary-color-filled); +} + +@media print { + .ProseMirror .page-break { + break-before: always; + page-break-before: always; + visibility: hidden; + border: none; + margin: 0; + } + + .ProseMirror .page-break::after { + content: none; + } +} diff --git a/apps/server/src/collaboration/collaboration.util.ts b/apps/server/src/collaboration/collaboration.util.ts index 5787e2e3a..554aa43bd 100644 --- a/apps/server/src/collaboration/collaboration.util.ts +++ b/apps/server/src/collaboration/collaboration.util.ts @@ -26,6 +26,7 @@ import { TiptapVideo, TiptapAudio, TiptapPdf, + PageBreak, TrailingNode, Attachment, Drawio, @@ -94,6 +95,7 @@ export const tiptapExtensions = [ TiptapVideo, TiptapAudio, TiptapPdf, + PageBreak, Callout, Attachment, CustomCodeBlock, diff --git a/packages/editor-ext/src/index.ts b/packages/editor-ext/src/index.ts index 354b1a617..003d22886 100644 --- a/packages/editor-ext/src/index.ts +++ b/packages/editor-ext/src/index.ts @@ -31,5 +31,6 @@ export * from "./lib/recreate-transform"; export * from "./lib/columns"; export * from "./lib/status"; export * from "./lib/pdf"; +export * from "./lib/page-break"; export * from "./lib/resizable-nodeview"; diff --git a/packages/editor-ext/src/lib/page-break/index.ts b/packages/editor-ext/src/lib/page-break/index.ts new file mode 100644 index 000000000..701b20b78 --- /dev/null +++ b/packages/editor-ext/src/lib/page-break/index.ts @@ -0,0 +1 @@ +export * from "./page-break"; diff --git a/packages/editor-ext/src/lib/page-break/page-break.ts b/packages/editor-ext/src/lib/page-break/page-break.ts new file mode 100644 index 000000000..f8991b266 --- /dev/null +++ b/packages/editor-ext/src/lib/page-break/page-break.ts @@ -0,0 +1,60 @@ +import { mergeAttributes, Node } from "@tiptap/core"; + +export interface PageBreakOptions { + HTMLAttributes: Record; +} + +declare module "@tiptap/core" { + interface Commands { + pageBreak: { + setPageBreak: () => ReturnType; + }; + } +} + +export const PageBreak = Node.create({ + name: "pageBreak", + + group: "block", + + atom: true, + + selectable: true, + + addOptions() { + return { + HTMLAttributes: {}, + }; + }, + + parseHTML() { + return [ + { + tag: `div[data-type="${this.name}"]`, + }, + ]; + }, + + renderHTML({ HTMLAttributes }) { + return [ + "div", + mergeAttributes( + { "data-type": this.name, class: "page-break" }, + this.options.HTMLAttributes, + HTMLAttributes, + ), + ]; + }, + + addCommands() { + return { + setPageBreak: + () => + ({ chain }) => + chain() + .insertContent({ type: this.name }) + .focus() + .run(), + }; + }, +}); From f758091b2af8341758e05ef2a82b27ee32f09672 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Thu, 14 May 2026 13:11:28 +0100 Subject: [PATCH 41/63] perf(permissions): cache space role and page edit lookups (#2208) --- apps/server/src/common/helpers/cache-keys.ts | 8 ++ apps/server/src/common/helpers/with-cache.ts | 27 ++++ .../repos/page/page-permission.repo.ts | 123 ++++++++---------- .../database/repos/space/space-member.repo.ts | 55 +++++--- 4 files changed, 125 insertions(+), 88 deletions(-) create mode 100644 apps/server/src/common/helpers/with-cache.ts diff --git a/apps/server/src/common/helpers/cache-keys.ts b/apps/server/src/common/helpers/cache-keys.ts index 570c96d88..38b24d20e 100644 --- a/apps/server/src/common/helpers/cache-keys.ts +++ b/apps/server/src/common/helpers/cache-keys.ts @@ -1,3 +1,11 @@ export const CacheKey = { LICENSE_VALID: (workspaceId: string) => `license:valid:${workspaceId}`, + SPACE_ROLES: (userId: string, spaceId: string) => + `perm:space-roles:${userId}:${spaceId}`, + PAGE_CAN_EDIT: (userId: string, pageId: string) => + `perm:can-edit:${userId}:${pageId}`, }; + +// Permission caches dedupe repeated checks within and across short request bursts. +// 5s keeps staleness on revocations bounded. +export const PERMISSION_CACHE_TTL_MS = 5_000; diff --git a/apps/server/src/common/helpers/with-cache.ts b/apps/server/src/common/helpers/with-cache.ts new file mode 100644 index 000000000..2db1d3c02 --- /dev/null +++ b/apps/server/src/common/helpers/with-cache.ts @@ -0,0 +1,27 @@ +import { Cache } from 'cache-manager'; + +export async function withCache( + cacheManager: Cache, + key: string, + ttlMs: number, + fn: () => Promise, +): Promise { + try { + const cached = await cacheManager.get<{ v: T }>(key); + if (cached !== undefined && cached !== null) { + return cached.v; + } + } catch (err) { + console.warn(`[withCache] get failed for "${key}", falling back to source`, err); + } + + const value = await fn(); + + try { + await cacheManager.set(key, { v: value }, ttlMs); + } catch (err) { + console.warn(`[withCache] set failed for "${key}"`, err); + } + + return value; +} diff --git a/apps/server/src/database/repos/page/page-permission.repo.ts b/apps/server/src/database/repos/page/page-permission.repo.ts index fbd7423ce..f753526cd 100644 --- a/apps/server/src/database/repos/page/page-permission.repo.ts +++ b/apps/server/src/database/repos/page/page-permission.repo.ts @@ -1,4 +1,6 @@ -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { Cache } from 'cache-manager'; import { InjectKysely } from 'nestjs-kysely'; import { KyselyDB, KyselyTransaction } from '@docmost/db/types/kysely.types'; import { dbOrTx } from '@docmost/db/utils'; @@ -17,6 +19,11 @@ import { executeWithCursorPagination, } from '@docmost/db/pagination/cursor-pagination'; import { PagePermissionMember } from './types/page-permission.types'; +import { withCache } from '../../../common/helpers/with-cache'; +import { + CacheKey, + PERMISSION_CACHE_TTL_MS, +} from '../../../common/helpers/cache-keys'; export { PagePermissionMember } from './types/page-permission.types'; @@ -25,6 +32,7 @@ export class PagePermissionRepo { constructor( @InjectKysely() private readonly db: KyselyDB, private readonly groupRepo: GroupRepo, + @Inject(CACHE_MANAGER) private readonly cacheManager: Cache, ) {} async findPageAccessByPageId( @@ -361,40 +369,8 @@ export class PagePermissionRepo { * Check if user can access a page by verifying they have permission on ALL restricted ancestors. */ async canUserAccessPage(userId: string, pageId: string): Promise { - const deniedAncestor = await this.db - .withRecursive('ancestors', (qb) => - qb - .selectFrom('pages') - .select(['pages.id as ancestorId', 'pages.parentPageId']) - .where('pages.id', '=', pageId) - .unionAll((eb) => - eb - .selectFrom('pages') - .innerJoin('ancestors', 'ancestors.parentPageId', 'pages.id') - .select(['pages.id as ancestorId', 'pages.parentPageId']), - ), - ) - .selectFrom('ancestors') - .innerJoin('pageAccess', 'pageAccess.pageId', 'ancestors.ancestorId') - .leftJoin('pagePermissions', (join) => - join - .onRef('pagePermissions.pageAccessId', '=', 'pageAccess.id') - .on((eb) => - eb.or([ - eb('pagePermissions.userId', '=', userId), - eb( - 'pagePermissions.groupId', - 'in', - this.userGroupIdsSubquery(eb, userId), - ), - ]), - ), - ) - .select('pageAccess.pageId') - .where('pagePermissions.id', 'is', null) - .executeTakeFirst(); - - return !deniedAncestor; + const { canAccess } = await this.canUserEditPage(userId, pageId); + return canAccess; } /** @@ -412,43 +388,50 @@ export class PagePermissionRepo { canAccess: boolean; canEdit: boolean; }> { - const result = await sql<{ - canAccess: boolean | null; - canEdit: boolean | null; - }>` - WITH RECURSIVE ancestors AS ( - SELECT id AS ancestor_id, parent_page_id, 0 AS depth - FROM pages - WHERE id = ${pageId}::uuid - UNION ALL - SELECT p.id, p.parent_page_id, a.depth + 1 - FROM pages p - JOIN ancestors a ON a.parent_page_id = p.id - ) - SELECT - bool_and(pp.id IS NOT NULL) AS "canAccess", - -- nearest restricted ancestor's highest role wins (DESC: 'writer' > 'reader', NULLS LAST: no-permission after real roles) - (array_agg(pp.role ORDER BY a.depth ASC, pp.role DESC NULLS LAST))[1] = 'writer' AS "canEdit" - FROM ancestors a - JOIN page_access pa ON pa.page_id = a.ancestor_id - LEFT JOIN page_permissions pp ON pp.page_access_id = pa.id - AND ( - pp.user_id = ${userId}::uuid - OR pp.group_id IN ( - SELECT gu.group_id FROM group_users gu WHERE gu.user_id = ${userId}::uuid + return withCache( + this.cacheManager, + CacheKey.PAGE_CAN_EDIT(userId, pageId), + PERMISSION_CACHE_TTL_MS, + async () => { + const result = await sql<{ + canAccess: boolean | null; + canEdit: boolean | null; + }>` + WITH RECURSIVE ancestors AS ( + SELECT id AS ancestor_id, parent_page_id, 0 AS depth + FROM pages + WHERE id = ${pageId}::uuid + UNION ALL + SELECT p.id, p.parent_page_id, a.depth + 1 + FROM pages p + JOIN ancestors a ON a.parent_page_id = p.id ) - ) - `.execute(this.db); + SELECT + bool_and(pp.id IS NOT NULL) AS "canAccess", + -- nearest restricted ancestor's highest role wins (DESC: 'writer' > 'reader', NULLS LAST: no-permission after real roles) + (array_agg(pp.role ORDER BY a.depth ASC, pp.role DESC NULLS LAST))[1] = 'writer' AS "canEdit" + FROM ancestors a + JOIN page_access pa ON pa.page_id = a.ancestor_id + LEFT JOIN page_permissions pp ON pp.page_access_id = pa.id + AND ( + pp.user_id = ${userId}::uuid + OR pp.group_id IN ( + SELECT gu.group_id FROM group_users gu WHERE gu.user_id = ${userId}::uuid + ) + ) + `.execute(this.db); - const row = result.rows[0]; - if (!row || row.canAccess === null) { - return { hasAnyRestriction: false, canAccess: true, canEdit: true }; - } - return { - hasAnyRestriction: true, - canAccess: row.canAccess, - canEdit: row.canAccess && (row.canEdit ?? false), - }; + const row = result.rows[0]; + if (!row || row.canAccess === null) { + return { hasAnyRestriction: false, canAccess: true, canEdit: true }; + } + return { + hasAnyRestriction: true, + canAccess: row.canAccess, + canEdit: row.canAccess && (row.canEdit ?? false), + }; + }, + ); } /** diff --git a/apps/server/src/database/repos/space/space-member.repo.ts b/apps/server/src/database/repos/space/space-member.repo.ts index 50961802f..6711c30c7 100644 --- a/apps/server/src/database/repos/space/space-member.repo.ts +++ b/apps/server/src/database/repos/space/space-member.repo.ts @@ -1,4 +1,6 @@ -import { BadRequestException, Injectable } from '@nestjs/common'; +import { BadRequestException, Inject, Injectable } from '@nestjs/common'; +import { CACHE_MANAGER } from '@nestjs/cache-manager'; +import { Cache } from 'cache-manager'; import { InjectKysely } from 'nestjs-kysely'; import { KyselyDB, KyselyTransaction } from '@docmost/db/types/kysely.types'; import { dbOrTx } from '@docmost/db/utils'; @@ -13,6 +15,11 @@ import { MemberInfo, UserSpaceRole } from './types'; import { executeWithCursorPagination } from '@docmost/db/pagination/cursor-pagination'; import { GroupRepo } from '@docmost/db/repos/group/group.repo'; import { SpaceRepo } from '@docmost/db/repos/space/space.repo'; +import { withCache } from '../../../common/helpers/with-cache'; +import { + CacheKey, + PERMISSION_CACHE_TTL_MS, +} from '../../../common/helpers/cache-keys'; @Injectable() export class SpaceMemberRepo { @@ -20,6 +27,7 @@ export class SpaceMemberRepo { @InjectKysely() private readonly db: KyselyDB, private readonly groupRepo: GroupRepo, private readonly spaceRepo: SpaceRepo, + @Inject(CACHE_MANAGER) private readonly cacheManager: Cache, ) {} async insertSpaceMember( @@ -214,25 +222,36 @@ export class SpaceMemberRepo { userId: string, spaceId: string, ): Promise { - const roles = await this.db - .selectFrom('spaceMembers') - .select(['userId', 'role']) - .where('userId', '=', userId) - .where('spaceId', '=', spaceId) - .unionAll( - this.db + return withCache( + this.cacheManager, + CacheKey.SPACE_ROLES(userId, spaceId), + PERMISSION_CACHE_TTL_MS, + async () => { + const roles = await this.db .selectFrom('spaceMembers') - .innerJoin('groupUsers', 'groupUsers.groupId', 'spaceMembers.groupId') - .select(['groupUsers.userId', 'spaceMembers.role']) - .where('groupUsers.userId', '=', userId) - .where('spaceMembers.spaceId', '=', spaceId), - ) - .execute(); + .select(['userId', 'role']) + .where('userId', '=', userId) + .where('spaceId', '=', spaceId) + .unionAll( + this.db + .selectFrom('spaceMembers') + .innerJoin( + 'groupUsers', + 'groupUsers.groupId', + 'spaceMembers.groupId', + ) + .select(['groupUsers.userId', 'spaceMembers.role']) + .where('groupUsers.userId', '=', userId) + .where('spaceMembers.spaceId', '=', spaceId), + ) + .execute(); - if (!roles || roles.length === 0) { - return undefined; - } - return roles; + if (!roles || roles.length === 0) { + return undefined; + } + return roles; + }, + ); } async getUserIdsWithSpaceAccess( From 82d065669dfb2617449aa664f34fae4fadd68f7d Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Thu, 14 May 2026 14:15:03 +0200 Subject: [PATCH 42/63] fix: page mode toggle no longer overwrites default preference (#1996) The header edit/read toggle now controls only the current session's mode without saving it as the user's preference. The saved preference (set in profile settings) is applied once on initial load and sticks across page navigations within the session, so navigating to a new page no longer resets the mode mid-session. Fixes #1693 --- .../src/features/editor/atoms/editor-atoms.ts | 5 +++++ .../src/features/editor/full-editor.tsx | 19 ++++++++++++++-- .../src/features/editor/page-editor.tsx | 22 +++++-------------- .../src/features/editor/title-editor.tsx | 21 +++++------------- .../components/header/page-header-menu.tsx | 4 ++-- .../user/components/page-state-pref.tsx | 22 +++++++++++++++++++ 6 files changed, 57 insertions(+), 36 deletions(-) diff --git a/apps/client/src/features/editor/atoms/editor-atoms.ts b/apps/client/src/features/editor/atoms/editor-atoms.ts index 8982765e4..c0873adfa 100644 --- a/apps/client/src/features/editor/atoms/editor-atoms.ts +++ b/apps/client/src/features/editor/atoms/editor-atoms.ts @@ -1,5 +1,6 @@ import { atom } from "jotai"; import { Editor } from "@tiptap/core"; +import { PageEditMode } from "@/features/user/types/user.types.ts"; export const pageEditorAtom = atom(null); @@ -12,3 +13,7 @@ export const yjsConnectionStatusAtom = atom(""); export const showAiMenuAtom = atom(false); export const showLinkMenuAtom = atom(false); + +// Current page's edit mode — initialized from the user's saved preference on +// first load, can be toggled locally without persisting to the server. +export const currentPageEditModeAtom = atom(PageEditMode.Edit); diff --git a/apps/client/src/features/editor/full-editor.tsx b/apps/client/src/features/editor/full-editor.tsx index 69bf2628f..57595b288 100644 --- a/apps/client/src/features/editor/full-editor.tsx +++ b/apps/client/src/features/editor/full-editor.tsx @@ -1,5 +1,5 @@ import classes from "@/features/editor/styles/editor.module.css"; -import React from "react"; +import React, { useEffect } from "react"; import { TitleEditor } from "@/features/editor/title-editor"; import PageEditor from "@/features/editor/page-editor"; import { @@ -24,6 +24,7 @@ import { FixedToolbar } from "@/features/editor/components/fixed-toolbar/fixed-t import { PageEditMode } from "@/features/user/types/user.types.ts"; import useToggleAside from "@/hooks/use-toggle-aside.tsx"; import clsx from "clsx"; +import { currentPageEditModeAtom } from "@/features/editor/atoms/editor-atoms.ts"; const MemoizedTitleEditor = React.memo(TitleEditor); const MemoizedPageEditor = React.memo(PageEditor); @@ -34,6 +35,10 @@ type PageCreator = { avatarUrl: string; }; +// Module-level flag: survives component unmount/remount on page navigation, +// reset only on full page reload (i.e. a new app session). +let defaultEditModeApplied = false; + export interface FullEditorProps { pageId: string; slugId: string; @@ -61,9 +66,19 @@ export function FullEditor({ const fullPageWidth = user.settings?.preferences?.fullPageWidth; const editorToolbarEnabled = user.settings?.preferences?.editorToolbar ?? false; + const [currentPageEditMode, setCurrentPageEditMode] = useAtom(currentPageEditModeAtom); const userPageEditMode = user.settings?.preferences?.pageEditMode ?? PageEditMode.Edit; - const isEditMode = userPageEditMode === PageEditMode.Edit; + const isEditMode = currentPageEditMode === PageEditMode.Edit; + + // Apply the user's saved preference only once on initial load, not on every + // page navigation — so the mode sticks across navigations within a session. + useEffect(() => { + if (!defaultEditModeApplied) { + setCurrentPageEditMode(userPageEditMode); + defaultEditModeApplied = true; + } + }, [userPageEditMode, setCurrentPageEditMode]); return ( Boolean(isComponentMounted.current && editorRef.current), [isComponentMounted], @@ -373,19 +373,9 @@ export default function PageEditor({ return () => clearTimeout(timeout); }, [yjsConnectionStatus, isSynced]); useEffect(() => { - // Only honor user default page edit mode preference and permissions - if (editor) { - if (userPageEditMode && editable) { - if (userPageEditMode === PageEditMode.Edit) { - editor.setEditable(true); - } else if (userPageEditMode === PageEditMode.Read) { - editor.setEditable(false); - } - } else { - editor.setEditable(false); - } - } - }, [userPageEditMode, editor, editable]); + if (!editor) return; + editor.setEditable(editable && currentPageEditMode === PageEditMode.Edit); + }, [currentPageEditMode, editor, editable]); const hasConnectedOnceRef = useRef(false); const [showStatic, setShowStatic] = useState(true); diff --git a/apps/client/src/features/editor/title-editor.tsx b/apps/client/src/features/editor/title-editor.tsx index e61d8c042..3ff2d7614 100644 --- a/apps/client/src/features/editor/title-editor.tsx +++ b/apps/client/src/features/editor/title-editor.tsx @@ -7,6 +7,7 @@ import { Text } from "@tiptap/extension-text"; import { Placeholder } from "@tiptap/extension-placeholder"; import { useAtomValue } from "jotai"; import { + currentPageEditModeAtom, pageEditorAtom, titleEditorAtom, } from "@/features/editor/atoms/editor-atoms"; @@ -24,7 +25,6 @@ import { useTranslation } from "react-i18next"; import EmojiCommand from "@/features/editor/extensions/emoji-command.ts"; import { UpdateEvent } from "@/features/websocket/types"; import localEmitter from "@/lib/local-emitter.ts"; -import { currentUserAtom } from "@/features/user/atoms/current-user-atom.ts"; import { PageEditMode } from "@/features/user/types/user.types.ts"; import { searchSpotlight } from "@/features/search/constants.ts"; import { platformModifierKey } from "@/lib"; @@ -52,9 +52,7 @@ export function TitleEditor({ const emit = useQueryEmit(); const navigate = useNavigate(); const [activePageId, setActivePageId] = useState(pageId); - const [currentUser] = useAtom(currentUserAtom); - const userPageEditMode = - currentUser?.user?.settings?.preferences?.pageEditMode ?? PageEditMode.Edit; + const currentPageEditMode = useAtomValue(currentPageEditModeAtom); const titleEditor = useEditor({ extensions: [ @@ -172,18 +170,9 @@ export function TitleEditor({ }, [pageId]); useEffect(() => { - if (titleEditor) { - if (userPageEditMode && editable) { - if (userPageEditMode === PageEditMode.Edit) { - titleEditor.setEditable(true); - } else if (userPageEditMode === PageEditMode.Read) { - titleEditor.setEditable(false); - } - } else { - titleEditor.setEditable(false); - } - } - }, [userPageEditMode, titleEditor, editable]); + if (!titleEditor) return; + titleEditor.setEditable(editable && currentPageEditMode === PageEditMode.Edit); + }, [currentPageEditMode, titleEditor, editable]); const openSearchDialog = () => { const event = new CustomEvent("openFindDialogFromEditor", {}); diff --git a/apps/client/src/features/page/components/header/page-header-menu.tsx b/apps/client/src/features/page/components/header/page-header-menu.tsx index 6e481b7aa..aaf23d6fd 100644 --- a/apps/client/src/features/page/components/header/page-header-menu.tsx +++ b/apps/client/src/features/page/components/header/page-header-menu.tsx @@ -40,7 +40,7 @@ import { yjsConnectionStatusAtom, } from "@/features/editor/atoms/editor-atoms.ts"; import { formattedDate } from "@/lib/time.ts"; -import { PageStateSegmentedControl } from "@/features/user/components/page-state-pref.tsx"; +import { PageEditModeToggle } from "@/features/user/components/page-state-pref.tsx"; import MovePageModal from "@/features/page/components/move-page-modal.tsx"; import { useTimeAgo } from "@/hooks/use-time-ago.tsx"; import { PageShareModal } from "@/ee/page-permission"; @@ -91,7 +91,7 @@ export default function PageHeaderMenu({ readOnly }: PageHeaderMenuProps) { <> - {!readOnly && } + {!readOnly && } diff --git a/apps/client/src/features/user/components/page-state-pref.tsx b/apps/client/src/features/user/components/page-state-pref.tsx index 712f5152f..c78a2e04b 100644 --- a/apps/client/src/features/user/components/page-state-pref.tsx +++ b/apps/client/src/features/user/components/page-state-pref.tsx @@ -6,6 +6,7 @@ import React, { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { PageEditMode } from "@/features/user/types/user.types.ts"; import { ResponsiveSettingsRow, ResponsiveSettingsContent, ResponsiveSettingsControl } from "@/components/ui/responsive-settings-row"; +import { currentPageEditModeAtom } from "@/features/editor/atoms/editor-atoms.ts"; export default function PageStatePref() { const { t } = useTranslation(); @@ -71,3 +72,24 @@ export function PageStateSegmentedControl({ /> ); } + +// Header variant: updates the current page's mode locally without persisting +// the preference to the server. +export function PageEditModeToggle({ size }: { size?: MantineSize }) { + const { t } = useTranslation(); + const [currentPageEditMode, setCurrentPageEditMode] = useAtom( + currentPageEditModeAtom, + ); + + return ( + setCurrentPageEditMode(v as PageEditMode)} + data={[ + { label: t("Edit"), value: PageEditMode.Edit }, + { label: t("Read"), value: PageEditMode.Read }, + ]} + /> + ); +} From 932c1ad5b73b14b9ea5a1f3ff1db0fea05a380b1 Mon Sep 17 00:00:00 2001 From: Peter Tripp Date: Thu, 14 May 2026 09:41:10 -0400 Subject: [PATCH 43/63] Better trash (#2190) * Better trash I recently lost a bunch of time editing and searching for pages that were actually in the Trash. Docmost intentionally tries to not link to Trashed pages, but the url of that Trashed page and any inbound links still work. This makes it clearer when a page you are interacting with is in the Trash. - /trash - Refactored banner into `trash-banner.tsx` - Refactored "Restore" modal into `use-restore-page-modal.tsx` - Page (when isDeleted) - Add: `trash-banner.tsx` - Add breadcrumbs: `Parent / Child / Page (Deleted)` - Change: Deleted Pages are read-only - Replace "Move to Trash" with "Restore" in page menu (invokes `use-restore-page-modal`) I tried very hard to keep this simple and re-use existing translation strings wherever possible. * cleanup --------- Co-authored-by: Philipinho <16838612+Philipinho@users.noreply.github.com> --- .../public/locales/en-US/translation.json | 3 + .../src/components/layouts/global/aside.tsx | 22 ++- .../src/features/editor/full-editor.tsx | 12 +- .../components/header/page-header-menu.tsx | 9 ++ .../page/hooks/use-restore-page-modal.tsx | 30 ++++ .../src/features/page/queries/page-query.ts | 26 +++- .../trash/components/deleted-page-banner.tsx | 140 ++++++++++++++++++ .../page/trash/components/trash-banner.tsx | 21 +++ .../features/page/trash/components/trash.tsx | 36 +---- apps/client/src/pages/page/page.tsx | 2 +- apps/server/src/core/page/page.controller.ts | 1 + .../src/database/repos/page/page.repo.ts | 5 + 12 files changed, 265 insertions(+), 42 deletions(-) create mode 100644 apps/client/src/features/page/hooks/use-restore-page-modal.tsx create mode 100644 apps/client/src/features/page/trash/components/deleted-page-banner.tsx create mode 100644 apps/client/src/features/page/trash/components/trash-banner.tsx diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index e85f2af23..d59aa94b9 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -71,6 +71,7 @@ "Export": "Export", "Failed to create page": "Failed to create page", "Failed to delete page": "Failed to delete page", + "Failed to restore page": "Failed to restore page", "Failed to fetch recent pages": "Failed to fetch recent pages", "Failed to import pages": "Failed to import pages", "Failed to load page. An error occurred.": "Failed to load page. An error occurred.", @@ -581,6 +582,8 @@ "Move to trash": "Move to trash", "Move this page to trash?": "Move this page to trash?", "Restore page": "Restore page", + "Permanently delete": "Permanently delete", + "{{name}} moved this page to Trash {{time}}.": "{{name}} moved this page to Trash {{time}}.", "Page moved to trash": "Page moved to trash", "Page restored successfully": "Page restored successfully", "Deleted by": "Deleted by", diff --git a/apps/client/src/components/layouts/global/aside.tsx b/apps/client/src/components/layouts/global/aside.tsx index 73e6a381d..23ebe7b7c 100644 --- a/apps/client/src/components/layouts/global/aside.tsx +++ b/apps/client/src/components/layouts/global/aside.tsx @@ -1,4 +1,5 @@ -import { Box, ScrollArea, Text } from "@mantine/core"; +import { ActionIcon, Box, Group, ScrollArea, Text, Tooltip } from "@mantine/core"; +import { IconX } from "@tabler/icons-react"; import CommentListWithTabs from "@/features/comment/components/comment-list-with-tabs.tsx"; import { useAtom } from "jotai"; import { asideStateAtom } from "@/components/layouts/global/hooks/atoms/sidebar-atom.ts"; @@ -11,9 +12,10 @@ import AsideChatPanel from "@/ee/ai-chat/components/aside-chat-panel"; import { PageDetailsAside } from "@/features/page-details/components/page-details-aside.tsx"; export default function Aside() { - const [{ tab }] = useAtom(asideStateAtom); + const [{ tab }, setAsideState] = useAtom(asideStateAtom); const { t } = useTranslation(); const pageEditor = useAtomValue(pageEditorAtom); + const closeAside = () => setAsideState((s) => ({ ...s, isAsideOpen: false })); let title: string; let component: ReactNode; @@ -45,9 +47,19 @@ export default function Aside() { {component && ( <> {tab !== "chat" && ( - - {t(title)} - + + {t(title)} + + + + + + )} {tab === "comments" || tab === "chat" ? ( diff --git a/apps/client/src/features/editor/full-editor.tsx b/apps/client/src/features/editor/full-editor.tsx index 57595b288..23a506448 100644 --- a/apps/client/src/features/editor/full-editor.tsx +++ b/apps/client/src/features/editor/full-editor.tsx @@ -23,13 +23,16 @@ import { IContributor } from "@/features/page/types/page.types.ts"; import { FixedToolbar } from "@/features/editor/components/fixed-toolbar/fixed-toolbar"; import { PageEditMode } from "@/features/user/types/user.types.ts"; import useToggleAside from "@/hooks/use-toggle-aside.tsx"; +import { DeletedPageBanner } from "@/features/page/trash/components/deleted-page-banner.tsx"; import clsx from "clsx"; import { currentPageEditModeAtom } from "@/features/editor/atoms/editor-atoms.ts"; const MemoizedTitleEditor = React.memo(TitleEditor); const MemoizedPageEditor = React.memo(PageEditor); +const MemoizedFixedToolbar = React.memo(FixedToolbar); +const MemoizedDeletedPageBanner = React.memo(DeletedPageBanner); -type PageCreator = { +type PageUser = { id: string; name: string; avatarUrl: string; @@ -46,7 +49,7 @@ export interface FullEditorProps { content: string; spaceSlug: string; editable: boolean; - creator?: PageCreator; + creator?: PageUser; contributors?: IContributor[]; canComment?: boolean; } @@ -86,7 +89,8 @@ export function FullEditor({ size={!fullPageWidth && 900} className={classes.editor} > - {editorToolbarEnabled && editable && isEditMode && } + {editorToolbarEnabled && editable && isEditMode && } + diff --git a/apps/client/src/features/page/hooks/use-restore-page-modal.tsx b/apps/client/src/features/page/hooks/use-restore-page-modal.tsx new file mode 100644 index 000000000..f2089f37f --- /dev/null +++ b/apps/client/src/features/page/hooks/use-restore-page-modal.tsx @@ -0,0 +1,30 @@ +import { modals } from "@mantine/modals"; +import { Text } from "@mantine/core"; +import { useTranslation } from "react-i18next"; + +type UseRestoreModalProps = { + title?: string | null; + onConfirm: () => void; +}; + +export function useRestorePageModal() { + const { t } = useTranslation(); + const openRestoreModal = ({ title, onConfirm }: UseRestoreModalProps) => { + modals.openConfirmModal({ + title: t("Restore page"), + children: ( + + {t("Restore '{{title}}' and its sub-pages?", { + title: title || t("Untitled"), + })} + + ), + centered: true, + labels: { confirm: t("Restore"), cancel: t("Cancel") }, + confirmProps: { color: "blue" }, + onConfirm, + }); + }; + + return { openRestoreModal } as const; +} diff --git a/apps/client/src/features/page/queries/page-query.ts b/apps/client/src/features/page/queries/page-query.ts index 1ed704ce1..11ba7f32d 100644 --- a/apps/client/src/features/page/queries/page-query.ts +++ b/apps/client/src/features/page/queries/page-query.ts @@ -117,10 +117,20 @@ export function useUpdatePageMutation() { } export function useRemovePageMutation() { + const { t } = useTranslation(); return useMutation({ mutationFn: (pageId: string) => deletePage(pageId, false), onSuccess: (_, pageId) => { - notifications.show({ message: "Page moved to trash" }); + notifications.show({ message: t("Page moved to trash") }); + + // Stamp deletedAt so a re-visit shows the trash banner, not stale state. + const cached = queryClient.getQueryData(["pages", pageId]); + if (cached) { + const stamped = { ...cached, deletedAt: new Date() }; + queryClient.setQueryData(["pages", cached.id], stamped); + queryClient.setQueryData(["pages", cached.slugId], stamped); + } + invalidateOnDeletePage(pageId); queryClient.invalidateQueries({ predicate: (item) => @@ -128,7 +138,7 @@ export function useRemovePageMutation() { }); }, onError: (error) => { - notifications.show({ message: "Failed to delete page", color: "red" }); + notifications.show({ message: t("Failed to delete page"), color: "red" }); }, }); } @@ -162,13 +172,14 @@ export function useMovePageMutation() { } export function useRestorePageMutation() { + const { t } = useTranslation(); const [treeData, setTreeData] = useAtom(treeDataAtom); const emit = useQueryEmit(); return useMutation({ mutationFn: (pageId: string) => restorePage(pageId), onSuccess: async (restoredPage) => { - notifications.show({ message: "Page restored successfully" }); + notifications.show({ message: t("Page restored successfully") }); // Check if the page already exists in the tree (it shouldn't) if (!treeModel.find(treeData, restoredPage.id)) { @@ -222,9 +233,16 @@ export function useRestorePageMutation() { await queryClient.invalidateQueries({ queryKey: ["trash-list", restoredPage.spaceId], }); + + // Merge — restore endpoint returns a skinny page; + // Replace would strip space/permissions/content and break the editor. + const merge = (cached: IPage | undefined) => + cached ? { ...cached, ...restoredPage } : cached; + queryClient.setQueryData(["pages", restoredPage.id], merge); + queryClient.setQueryData(["pages", restoredPage.slugId], merge); }, onError: (error) => { - notifications.show({ message: "Failed to restore page", color: "red" }); + notifications.show({ message: t("Failed to restore page"), color: "red" }); }, }); } diff --git a/apps/client/src/features/page/trash/components/deleted-page-banner.tsx b/apps/client/src/features/page/trash/components/deleted-page-banner.tsx new file mode 100644 index 000000000..f01a6ab49 --- /dev/null +++ b/apps/client/src/features/page/trash/components/deleted-page-banner.tsx @@ -0,0 +1,140 @@ +import { ActionIcon, Button, Group, Paper, Text, Tooltip } from "@mantine/core"; +import { IconRestore, IconTrash } from "@tabler/icons-react"; +import { useNavigate } from "react-router-dom"; +import { Trans, useTranslation } from "react-i18next"; +import { useTimeAgo } from "@/hooks/use-time-ago.tsx"; +import { useRestorePageModal } from "@/features/page/hooks/use-restore-page-modal.tsx"; +import { useDeletePageModal } from "@/features/page/hooks/use-delete-page-modal.tsx"; +import { + useDeletePageMutation, + usePageQuery, + useRestorePageMutation, +} from "@/features/page/queries/page-query.ts"; +import { getSpaceUrl } from "@/lib/config.ts"; +import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts"; +import { useSpaceAbility } from "@/features/space/permissions/use-space-ability.ts"; +import { + SpaceCaslAction, + SpaceCaslSubject, +} from "@/features/space/permissions/permissions.type.ts"; + +type DeletedPageBannerProps = { + slugId: string; +}; + +export function DeletedPageBanner({ slugId }: DeletedPageBannerProps) { + const { t } = useTranslation(); + const navigate = useNavigate(); + const { data: page } = usePageQuery({ pageId: slugId }); + const { data: space } = useGetSpaceBySlugQuery(page?.space?.slug); + const spaceAbility = useSpaceAbility(space?.membership?.permissions); + const deletedTimeAgo = useTimeAgo(page?.deletedAt); + const restorePageMutation = useRestorePageMutation(); + const deletePageMutation = useDeletePageMutation(); + const { openRestoreModal } = useRestorePageModal(); + const { openDeleteModal } = useDeletePageModal(); + + if (!page?.deletedAt) return null; + + const canRestore = spaceAbility.can( + SpaceCaslAction.Edit, + SpaceCaslSubject.Page, + ); + const canPermanentlyDelete = spaceAbility.can( + SpaceCaslAction.Manage, + SpaceCaslSubject.Settings, + ); + const actorName = page.deletedBy?.name ?? t("Someone"); + + const handleRestore = () => { + openRestoreModal({ + title: page.title, + onConfirm: () => restorePageMutation.mutate(page.id), + }); + }; + + const handlePermanentDelete = () => { + openDeleteModal({ + isPermanent: true, + onConfirm: async () => { + await deletePageMutation.mutateAsync(page.id); + navigate(getSpaceUrl(page.space?.slug)); + }, + }); + }; + + const hasAnyAction = canRestore || canPermanentlyDelete; + + return ( + + + + }} + /> + + {hasAnyAction && ( + <> + + {canRestore && ( + + )} + {canPermanentlyDelete && ( + + )} + + + {canRestore && ( + + + + + + )} + {canPermanentlyDelete && ( + + + + + + )} + + + )} + + + ); +} diff --git a/apps/client/src/features/page/trash/components/trash-banner.tsx b/apps/client/src/features/page/trash/components/trash-banner.tsx new file mode 100644 index 000000000..90ec4a066 --- /dev/null +++ b/apps/client/src/features/page/trash/components/trash-banner.tsx @@ -0,0 +1,21 @@ +import { Alert, Text } from "@mantine/core"; +import { IconInfoCircle } from "@tabler/icons-react"; +import { useAtomValue } from "jotai"; +import { useTranslation } from "react-i18next"; +import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts"; + +export function TrashBanner() { + const { t } = useTranslation(); + const workspace = useAtomValue(workspaceAtom); + const retentionDays = workspace?.trashRetentionDays ?? 30; + + return ( + } variant="light" color="red"> + + {t("Pages in trash will be permanently deleted after {{count}} days.", { + count: retentionDays, + })} + + + ); +} diff --git a/apps/client/src/features/page/trash/components/trash.tsx b/apps/client/src/features/page/trash/components/trash.tsx index de7e7ca4a..da33d828f 100644 --- a/apps/client/src/features/page/trash/components/trash.tsx +++ b/apps/client/src/features/page/trash/components/trash.tsx @@ -7,17 +7,16 @@ import { Group, ActionIcon, Text, - Alert, Stack, Menu, } from "@mantine/core"; import { - IconInfoCircle, IconDots, IconRestore, IconTrash, IconFileDescription, } from "@tabler/icons-react"; +import { TrashBanner } from "@/features/page/trash/components/trash-banner.tsx"; import { useDeletedPagesQuery, useRestorePageMutation, @@ -31,12 +30,10 @@ import TrashPageContentModal from "@/features/page/trash/components/trash-page-c import { UserInfo } from "@/components/common/user-info.tsx"; import Paginate from "@/components/common/paginate.tsx"; import { useCursorPaginate } from "@/hooks/use-cursor-paginate"; -import { useAtom } from "jotai"; -import { workspaceAtom } from "@/features/user/atoms/current-user-atom.ts"; +import { useRestorePageModal } from "@/features/page/hooks/use-restore-page-modal.tsx"; export default function Trash() { const { t } = useTranslation(); - const [workspace] = useAtom(workspaceAtom); const { spaceSlug } = useParams(); const { cursor, goNext, goPrev } = useCursorPaginate(); const { data: space } = useGetSpaceBySlugQuery(spaceSlug); @@ -45,6 +42,7 @@ export default function Trash() { }); const restorePageMutation = useRestorePageMutation(); const deletePageMutation = useDeletePageMutation(); + const { openRestoreModal } = useRestorePageModal(); const [selectedPage, setSelectedPage] = useState<{ title: string; @@ -78,23 +76,6 @@ export default function Trash() { }); }; - const openRestoreModal = (pageId: string, pageTitle: string) => { - modals.openConfirmModal({ - title: t("Restore page"), - children: ( - - {t("Restore '{{title}}' and its sub-pages?", { - title: pageTitle || "Untitled", - })} - - ), - centered: true, - labels: { confirm: t("Restore"), cancel: t("Cancel") }, - confirmProps: { color: "blue" }, - onConfirm: () => handleRestorePage(pageId), - }); - }; - const hasPages = deletedPages && deletedPages.items.length > 0; const handlePageClick = (page: any) => { @@ -109,11 +90,7 @@ export default function Trash() { {t("Trash")} - } variant="light" color="red"> - - {t("Pages in trash will be permanently deleted after {{count}} days.", { count: workspace?.trashRetentionDays ?? 30 })} - - + {isLoading || !deletedPages ? ( <> @@ -181,7 +158,10 @@ export default function Trash() { } onClick={() => - openRestoreModal(page.id, page.title) + openRestoreModal({ + title: page.title, + onConfirm: () => handleRestorePage(page.id), + }) } > {t("Restore")} diff --git a/apps/client/src/pages/page/page.tsx b/apps/client/src/pages/page/page.tsx index b4e3baa80..1eecd2512 100644 --- a/apps/client/src/pages/page/page.tsx +++ b/apps/client/src/pages/page/page.tsx @@ -52,7 +52,7 @@ function PageContent({ pageSlug }: { pageSlug: string | undefined }) { } = usePageQuery({ pageId: extractPageSlugId(pageSlug) }); const { data: space } = useGetSpaceBySlugQuery(page?.space?.slug); - const canEdit = page?.permissions?.canEdit ?? false; + const canEdit = !page?.deletedAt && (page?.permissions?.canEdit ?? false); const canComment = canEdit || (space?.settings?.comments?.allowViewerComments === true); diff --git a/apps/server/src/core/page/page.controller.ts b/apps/server/src/core/page/page.controller.ts index 5ce077508..773774ea7 100644 --- a/apps/server/src/core/page/page.controller.ts +++ b/apps/server/src/core/page/page.controller.ts @@ -76,6 +76,7 @@ export class PageController { includeCreator: true, includeLastUpdatedBy: true, includeContributors: true, + includeDeletedBy: true, }); if (!page) { diff --git a/apps/server/src/database/repos/page/page.repo.ts b/apps/server/src/database/repos/page/page.repo.ts index 6b17e37f9..259e1bd33 100644 --- a/apps/server/src/database/repos/page/page.repo.ts +++ b/apps/server/src/database/repos/page/page.repo.ts @@ -54,6 +54,7 @@ export class PageRepo { includeCreator?: boolean; includeLastUpdatedBy?: boolean; includeContributors?: boolean; + includeDeletedBy?: boolean; includeHasChildren?: boolean; withLock?: boolean; trx?: KyselyTransaction; @@ -83,6 +84,10 @@ export class PageRepo { query = query.select((eb) => this.withContributors(eb)); } + if (opts?.includeDeletedBy) { + query = query.select((eb) => this.withDeletedBy(eb)); + } + if (opts?.includeSpace) { query = query.select((eb) => this.withSpace(eb)); } From e41518a93db536fd53bcf678a679dd6c983bc862 Mon Sep 17 00:00:00 2001 From: Philipinho <16838612+Philipinho@users.noreply.github.com> Date: Thu, 14 May 2026 14:49:02 +0100 Subject: [PATCH 44/63] fix type --- apps/client/src/features/editor/full-editor.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/client/src/features/editor/full-editor.tsx b/apps/client/src/features/editor/full-editor.tsx index 23a506448..412a3b3de 100644 --- a/apps/client/src/features/editor/full-editor.tsx +++ b/apps/client/src/features/editor/full-editor.tsx @@ -69,7 +69,9 @@ export function FullEditor({ const fullPageWidth = user.settings?.preferences?.fullPageWidth; const editorToolbarEnabled = user.settings?.preferences?.editorToolbar ?? false; - const [currentPageEditMode, setCurrentPageEditMode] = useAtom(currentPageEditModeAtom); + const [currentPageEditMode, setCurrentPageEditMode] = useAtom( + currentPageEditModeAtom, + ); const userPageEditMode = user.settings?.preferences?.pageEditMode ?? PageEditMode.Edit; const isEditMode = currentPageEditMode === PageEditMode.Edit; @@ -78,7 +80,7 @@ export function FullEditor({ // page navigation — so the mode sticks across navigations within a session. useEffect(() => { if (!defaultEditModeApplied) { - setCurrentPageEditMode(userPageEditMode); + setCurrentPageEditMode(userPageEditMode as PageEditMode); defaultEditModeApplied = true; } }, [userPageEditMode, setCurrentPageEditMode]); @@ -89,7 +91,9 @@ export function FullEditor({ size={!fullPageWidth && 900} className={classes.editor} > - {editorToolbarEnabled && editable && isEditMode && } + {editorToolbarEnabled && editable && isEditMode && ( + + )} Date: Thu, 14 May 2026 15:06:51 +0100 Subject: [PATCH 45/63] fix collab module --- .../src/collaboration/server/collab-app.module.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/server/src/collaboration/server/collab-app.module.ts b/apps/server/src/collaboration/server/collab-app.module.ts index f0e27d41a..85738d1cb 100644 --- a/apps/server/src/collaboration/server/collab-app.module.ts +++ b/apps/server/src/collaboration/server/collab-app.module.ts @@ -2,6 +2,7 @@ import { Module } from '@nestjs/common'; import { AppController } from '../../app.controller'; import { AppService } from '../../app.service'; import { EnvironmentModule } from '../../integrations/environment/environment.module'; +import { EnvironmentService } from '../../integrations/environment/environment.service'; import { CollaborationModule } from '../collaboration.module'; import { DatabaseModule } from '@docmost/db/database.module'; import { QueueModule } from '../../integrations/queue/queue.module'; @@ -12,6 +13,8 @@ import { LoggerModule } from '../../common/logger/logger.module'; import { RedisModule } from '@nestjs-labs/nestjs-ioredis'; import { RedisConfigService } from '../../integrations/redis/redis-config.service'; import { CaslModule } from '../../core/casl/casl.module'; +import { CacheModule } from '@nestjs/cache-manager'; +import KeyvRedis from '@keyv/redis'; @Module({ imports: [ @@ -26,6 +29,18 @@ import { CaslModule } from '../../core/casl/casl.module'; RedisModule.forRootAsync({ useClass: RedisConfigService, }), + CacheModule.registerAsync({ + isGlobal: true, + useFactory: async (environmentService: EnvironmentService) => { + const redisUrl = environmentService.getRedisUrl(); + + return { + ttl: 5 * 1000, + stores: [new KeyvRedis(redisUrl)], + }; + }, + inject: [EnvironmentService], + }), ], controllers: [ AppController, From b7b99cb3b229196f7f00aaa02fe7a043c0a41134 Mon Sep 17 00:00:00 2001 From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com> Date: Fri, 15 May 2026 02:46:54 +0100 Subject: [PATCH 46/63] fix: code splitting and editor fixes (#2211) * fix table * fix code splitting * fix: editor ready check * fix codeblock/mermaid gap cursor * fix callout --- .../editor/components/audio/audio-menu.tsx | 3 +- .../components/callout/callout-menu.tsx | 4 +- .../components/columns/columns-menu.tsx | 6 +- .../editor/components/drawio/drawio-menu.tsx | 3 +- .../excalidraw/excalidraw-menu-lazy.tsx | 14 ++ .../components/excalidraw/excalidraw-menu.tsx | 3 +- .../excalidraw/excalidraw-view-lazy.tsx | 14 ++ .../editor/components/image/image-menu.tsx | 3 +- .../editor/components/pdf/pdf-menu.tsx | 8 +- .../components/subpages/subpages-menu.tsx | 2 + .../components/table/handle/column-handle.tsx | 7 +- .../components/table/handle/row-handle.tsx | 7 +- .../editor/components/table/table-menu.tsx | 3 +- .../editor/components/video/video-menu.tsx | 3 +- .../features/editor/extensions/extensions.ts | 2 +- .../src/features/editor/page-editor.tsx | 2 +- apps/client/vite.config.ts | 10 +- .../editor-ext/src/lib/callout/callout.ts | 72 +++++++++ .../custom-code-block/custom-code-block.ts | 139 ++++++++++++++++++ packages/editor-ext/src/lib/utils.ts | 9 ++ 20 files changed, 290 insertions(+), 24 deletions(-) create mode 100644 apps/client/src/features/editor/components/excalidraw/excalidraw-menu-lazy.tsx create mode 100644 apps/client/src/features/editor/components/excalidraw/excalidraw-view-lazy.tsx diff --git a/apps/client/src/features/editor/components/audio/audio-menu.tsx b/apps/client/src/features/editor/components/audio/audio-menu.tsx index 3ca1950da..eadc1afe5 100644 --- a/apps/client/src/features/editor/components/audio/audio-menu.tsx +++ b/apps/client/src/features/editor/components/audio/audio-menu.tsx @@ -2,6 +2,7 @@ import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react/menus"; import { findParentNode, posToDOMRect, useEditorState } from "@tiptap/react"; import { useCallback } from "react"; import { Node as PMNode } from "@tiptap/pm/model"; +import { isEditorReady } from "@docmost/editor-ext"; import { EditorMenuProps, ShouldShowProps, @@ -46,7 +47,7 @@ export function AudioMenu({ editor }: EditorMenuProps) { ); const getReferencedVirtualElement = useCallback(() => { - if (!editor) return; + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "audio"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/callout/callout-menu.tsx b/apps/client/src/features/editor/components/callout/callout-menu.tsx index 69c836934..3ce022dae 100644 --- a/apps/client/src/features/editor/components/callout/callout-menu.tsx +++ b/apps/client/src/features/editor/components/callout/callout-menu.tsx @@ -16,7 +16,7 @@ import { IconMoodSmile, IconNotes, } from "@tabler/icons-react"; -import { CalloutType, isTextSelected } from "@docmost/editor-ext"; +import { CalloutType, isEditorReady, isTextSelected } from "@docmost/editor-ext"; import { useTranslation } from "react-i18next"; import EmojiPicker from "@/components/ui/emoji-picker.tsx"; import classes from "../common/toolbar-menu.module.css"; @@ -55,7 +55,7 @@ export function CalloutMenu({ editor }: EditorMenuProps) { }); const getReferencedVirtualElement = useCallback(() => { - if (!editor) return; + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "callout"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/columns/columns-menu.tsx b/apps/client/src/features/editor/components/columns/columns-menu.tsx index 0ee99508c..4a1f041eb 100644 --- a/apps/client/src/features/editor/components/columns/columns-menu.tsx +++ b/apps/client/src/features/editor/components/columns/columns-menu.tsx @@ -19,7 +19,7 @@ import { IconCopy, IconTrash, } from "@tabler/icons-react"; -import { isTextSelected } from "@docmost/editor-ext"; +import { isEditorReady, isTextSelected } from "@docmost/editor-ext"; import type { WidthMode, ColumnsLayout } from "@docmost/editor-ext"; import { useTranslation } from "react-i18next"; import classes from "../common/toolbar-menu.module.css"; @@ -82,7 +82,7 @@ export function ColumnsMenu({ editor }: EditorMenuProps) { const shouldShow = useCallback( ({ state }: ShouldShowProps) => { - if (!state) return false; + if (!state || !isEditorReady(editor)) return false; if (!editor.isActive("columns")) return false; if (isTextSelected(editor)) return false; if (nodesWithMenus.some((name) => editor.isActive(name))) return false; @@ -121,7 +121,7 @@ export function ColumnsMenu({ editor }: EditorMenuProps) { }); const getReferencedVirtualElement = useCallback(() => { - if (!editor) return; + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "columns"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/drawio/drawio-menu.tsx b/apps/client/src/features/editor/components/drawio/drawio-menu.tsx index 869decd71..877911750 100644 --- a/apps/client/src/features/editor/components/drawio/drawio-menu.tsx +++ b/apps/client/src/features/editor/components/drawio/drawio-menu.tsx @@ -2,6 +2,7 @@ import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react/menus"; import { findParentNode, posToDOMRect, useEditorState } from "@tiptap/react"; import { useCallback, useEffect, useRef, useState } from "react"; import { Node as PMNode } from "@tiptap/pm/model"; +import { isEditorReady } from "@docmost/editor-ext"; import { EditorMenuProps, ShouldShowProps, @@ -81,7 +82,7 @@ export function DrawioMenu({ editor }: EditorMenuProps) { ); const getReferencedVirtualElement = useCallback(() => { - if (!editor) return; + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "drawio"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/excalidraw/excalidraw-menu-lazy.tsx b/apps/client/src/features/editor/components/excalidraw/excalidraw-menu-lazy.tsx new file mode 100644 index 000000000..acdf5440d --- /dev/null +++ b/apps/client/src/features/editor/components/excalidraw/excalidraw-menu-lazy.tsx @@ -0,0 +1,14 @@ +import { lazy, Suspense } from "react"; +import { EditorMenuProps } from "@/features/editor/components/table/types/types.ts"; + +const ExcalidrawMenu = lazy( + () => import("@/features/editor/components/excalidraw/excalidraw-menu.tsx"), +); + +export default function ExcalidrawMenuLazy(props: EditorMenuProps) { + return ( + + + + ); +} diff --git a/apps/client/src/features/editor/components/excalidraw/excalidraw-menu.tsx b/apps/client/src/features/editor/components/excalidraw/excalidraw-menu.tsx index fd3128062..823c2c213 100644 --- a/apps/client/src/features/editor/components/excalidraw/excalidraw-menu.tsx +++ b/apps/client/src/features/editor/components/excalidraw/excalidraw-menu.tsx @@ -2,6 +2,7 @@ import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react/menus"; import { findParentNode, posToDOMRect, useEditorState } from "@tiptap/react"; import { lazy, Suspense, useCallback, useEffect, useRef, useState } from "react"; import { Node as PMNode } from "@tiptap/pm/model"; +import { isEditorReady } from "@docmost/editor-ext"; import { EditorMenuProps, ShouldShowProps, @@ -94,7 +95,7 @@ export function ExcalidrawMenu({ editor }: EditorMenuProps) { ); const getReferencedVirtualElement = useCallback(() => { - if (!editor) return; + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "excalidraw"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/excalidraw/excalidraw-view-lazy.tsx b/apps/client/src/features/editor/components/excalidraw/excalidraw-view-lazy.tsx new file mode 100644 index 000000000..573a25dbd --- /dev/null +++ b/apps/client/src/features/editor/components/excalidraw/excalidraw-view-lazy.tsx @@ -0,0 +1,14 @@ +import { lazy, Suspense } from "react"; +import { NodeViewProps } from "@tiptap/react"; + +const ExcalidrawView = lazy( + () => import("@/features/editor/components/excalidraw/excalidraw-view.tsx"), +); + +export default function ExcalidrawViewLazy(props: NodeViewProps) { + return ( + + + + ); +} diff --git a/apps/client/src/features/editor/components/image/image-menu.tsx b/apps/client/src/features/editor/components/image/image-menu.tsx index 666fab7dc..1b2d00e7e 100644 --- a/apps/client/src/features/editor/components/image/image-menu.tsx +++ b/apps/client/src/features/editor/components/image/image-menu.tsx @@ -2,6 +2,7 @@ import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react/menus"; import { findParentNode, posToDOMRect, useEditorState } from "@tiptap/react"; import React, { useCallback, useRef } from "react"; import { Node as PMNode } from "@tiptap/pm/model"; +import { isEditorReady } from "@docmost/editor-ext"; import { EditorMenuProps, ShouldShowProps, @@ -56,7 +57,7 @@ export function ImageMenu({ editor }: EditorMenuProps) { ); const getReferencedVirtualElement = useCallback(() => { - if (!editor) return; + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "image"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/pdf/pdf-menu.tsx b/apps/client/src/features/editor/components/pdf/pdf-menu.tsx index 2104bfbc6..3fc8b6fd1 100644 --- a/apps/client/src/features/editor/components/pdf/pdf-menu.tsx +++ b/apps/client/src/features/editor/components/pdf/pdf-menu.tsx @@ -2,6 +2,7 @@ import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react/menus"; import { findParentNode, posToDOMRect, useEditorState } from "@tiptap/react"; import { useCallback } from "react"; import { Node as PMNode } from "@tiptap/pm/model"; +import { isEditorReady } from "@docmost/editor-ext"; import { EditorMenuProps, ShouldShowProps, @@ -37,9 +38,8 @@ export function PdfMenu({ editor }: EditorMenuProps) { const shouldShow = useCallback( ({ state }: ShouldShowProps) => { - if (!state || !editor.isActive("pdf")) { - return false; - } + if (!state || !isEditorReady(editor)) return false; + if (!editor.isActive("pdf")) return false; const { selection } = state; const dom = editor.view.nodeDOM(selection.from) as HTMLElement | null; @@ -51,7 +51,7 @@ export function PdfMenu({ editor }: EditorMenuProps) { ); const getReferencedVirtualElement = useCallback(() => { - if (!editor) return; + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "pdf"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/subpages/subpages-menu.tsx b/apps/client/src/features/editor/components/subpages/subpages-menu.tsx index 9f0544e67..a626e1ee2 100644 --- a/apps/client/src/features/editor/components/subpages/subpages-menu.tsx +++ b/apps/client/src/features/editor/components/subpages/subpages-menu.tsx @@ -6,6 +6,7 @@ import { ActionIcon, Tooltip } from "@mantine/core"; import { IconTrash } from "@tabler/icons-react"; import { useTranslation } from "react-i18next"; import { Editor } from "@tiptap/core"; +import { isEditorReady } from "@docmost/editor-ext"; interface SubpagesMenuProps { editor: Editor; @@ -33,6 +34,7 @@ export const SubpagesMenu = React.memo( ); const getReferenceClientRect = useCallback(() => { + if (!isEditorReady(editor)) return new DOMRect(); const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "subpages"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/table/handle/column-handle.tsx b/apps/client/src/features/editor/components/table/handle/column-handle.tsx index ccc459740..a46ac50d5 100644 --- a/apps/client/src/features/editor/components/table/handle/column-handle.tsx +++ b/apps/client/src/features/editor/components/table/handle/column-handle.tsx @@ -31,7 +31,12 @@ export const ColumnHandle = React.memo(function ColumnHandle({ // (the plugin re-emits `hoveringCell` with the mapped pos a tick later); // unmounting the source element here would make pragmatic-dnd silently // abort the active drag. - const lookupCellDom = editor.view.nodeDOM(anchorPos) as HTMLElement | null; + // `nodeDOM` is typed as `Node | null` — when `anchorPos` goes stale (e.g. + // an external drop reflows the doc before the plugin re-emits + // hoveringCell), it can resolve to a Text node, on which `.closest` is + // undefined. Filter to HTMLElement so downstream consumers stay safe. + const lookupDom = editor.view.nodeDOM(anchorPos); + const lookupCellDom = lookupDom instanceof HTMLElement ? lookupDom : null; const [cellDom, setCellDom] = useState(lookupCellDom); const lastCellDomRef = useRef(lookupCellDom); useEffect(() => { diff --git a/apps/client/src/features/editor/components/table/handle/row-handle.tsx b/apps/client/src/features/editor/components/table/handle/row-handle.tsx index 7a5483558..1f3e3cc51 100644 --- a/apps/client/src/features/editor/components/table/handle/row-handle.tsx +++ b/apps/client/src/features/editor/components/table/handle/row-handle.tsx @@ -29,7 +29,12 @@ export const RowHandle = React.memo(function RowHandle({ // See ColumnHandle for the rationale: keep the last valid cell DOM cached // so the handle div stays mounted across stale-anchor renders, otherwise // pragmatic-dnd silently aborts an in-flight drag. - const lookupCellDom = editor.view.nodeDOM(anchorPos) as HTMLElement | null; + // `nodeDOM` is typed as `Node | null` — when `anchorPos` goes stale (e.g. + // an external drop reflows the doc before the plugin re-emits + // hoveringCell), it can resolve to a Text node, on which `.closest` is + // undefined. Filter to HTMLElement so downstream consumers stay safe. + const lookupDom = editor.view.nodeDOM(anchorPos); + const lookupCellDom = lookupDom instanceof HTMLElement ? lookupDom : null; const [cellDom, setCellDom] = useState(lookupCellDom); const lastCellDomRef = useRef(lookupCellDom); useEffect(() => { diff --git a/apps/client/src/features/editor/components/table/table-menu.tsx b/apps/client/src/features/editor/components/table/table-menu.tsx index 3be7ec539..92cc318e9 100644 --- a/apps/client/src/features/editor/components/table/table-menu.tsx +++ b/apps/client/src/features/editor/components/table/table-menu.tsx @@ -18,7 +18,7 @@ import { IconTrashX, } from "@tabler/icons-react"; import { BubbleMenu } from "@tiptap/react/menus"; -import { isCellSelection, isTextSelected } from "@docmost/editor-ext"; +import { isCellSelection, isEditorReady, isTextSelected } from "@docmost/editor-ext"; import { useTranslation } from "react-i18next"; import classes from "../common/toolbar-menu.module.css"; @@ -38,6 +38,7 @@ export const TableMenu = React.memo( ); const getReferencedVirtualElement = useCallback(() => { + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "table"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/components/video/video-menu.tsx b/apps/client/src/features/editor/components/video/video-menu.tsx index 3f232625f..429e02f87 100644 --- a/apps/client/src/features/editor/components/video/video-menu.tsx +++ b/apps/client/src/features/editor/components/video/video-menu.tsx @@ -2,6 +2,7 @@ import { BubbleMenu as BaseBubbleMenu } from "@tiptap/react/menus"; import { findParentNode, posToDOMRect, useEditorState } from "@tiptap/react"; import { useCallback } from "react"; import { Node as PMNode } from "@tiptap/pm/model"; +import { isEditorReady } from "@docmost/editor-ext"; import { EditorMenuProps, ShouldShowProps, @@ -53,7 +54,7 @@ export function VideoMenu({ editor }: EditorMenuProps) { ); const getReferencedVirtualElement = useCallback(() => { - if (!editor) return; + if (!isEditorReady(editor)) return; const { selection } = editor.state; const predicate = (node: PMNode) => node.type.name === "video"; const parent = findParentNode(predicate)(selection); diff --git a/apps/client/src/features/editor/extensions/extensions.ts b/apps/client/src/features/editor/extensions/extensions.ts index 91411daef..9857b0551 100644 --- a/apps/client/src/features/editor/extensions/extensions.ts +++ b/apps/client/src/features/editor/extensions/extensions.ts @@ -85,7 +85,7 @@ import AudioView from "@/features/editor/components/audio/audio-view.tsx"; import AttachmentView from "@/features/editor/components/attachment/attachment-view.tsx"; import CodeBlockView from "@/features/editor/components/code-block/code-block-view.tsx"; import DrawioView from "../components/drawio/drawio-view"; -import ExcalidrawView from "@/features/editor/components/excalidraw/excalidraw-view.tsx"; +import ExcalidrawView from "@/features/editor/components/excalidraw/excalidraw-view-lazy.tsx"; import EmbedView from "@/features/editor/components/embed/embed-view.tsx"; import PdfView from "@/features/editor/components/pdf/pdf-view.tsx"; import SubpagesView from "@/features/editor/components/subpages/subpages-view.tsx"; diff --git a/apps/client/src/features/editor/page-editor.tsx b/apps/client/src/features/editor/page-editor.tsx index 9d53eec31..8521356ec 100644 --- a/apps/client/src/features/editor/page-editor.tsx +++ b/apps/client/src/features/editor/page-editor.tsx @@ -55,7 +55,7 @@ import { handleFileDrop, handlePaste, } from "@/features/editor/components/common/editor-paste-handler.tsx"; -import ExcalidrawMenu from "./components/excalidraw/excalidraw-menu"; +import ExcalidrawMenu from "./components/excalidraw/excalidraw-menu-lazy"; import DrawioMenu from "./components/drawio/drawio-menu"; import { useCollabToken } from "@/features/auth/queries/auth-query.tsx"; import SearchAndReplaceDialog from "@/features/editor/components/search-and-replace/search-and-replace-dialog.tsx"; diff --git a/apps/client/vite.config.ts b/apps/client/vite.config.ts index e6f9de48c..b230a29ff 100644 --- a/apps/client/vite.config.ts +++ b/apps/client/vite.config.ts @@ -38,12 +38,12 @@ export default defineConfig(({ mode }) => { build: { rolldownOptions: { output: { - codeSplitting: { + advancedChunks: { groups: [ - { name: "vendor-mantine", test: /@mantine/ }, - { name: "vendor-mermaid", test: /mermaid|cytoscape|elkjs/ }, - { name: "vendor-excalidraw", test: /excalidraw/ }, - { name: "vendor-katex", test: /katex/ }, + { + name: "vendor-mantine", + test: /[\\/]node_modules[\\/]@mantine[\\/]/, + }, ], }, }, diff --git a/packages/editor-ext/src/lib/callout/callout.ts b/packages/editor-ext/src/lib/callout/callout.ts index 898fc4152..a07a4a96c 100644 --- a/packages/editor-ext/src/lib/callout/callout.ts +++ b/packages/editor-ext/src/lib/callout/callout.ts @@ -162,6 +162,28 @@ export const Callout = Node.create({ return false; } + // Empty callout: delete the whole node so Backspace inside it isn't + // a no-op (isolating: true blocks the default join with the block + // above). + const calloutDepth = $from.depth - 1; + if (calloutDepth >= 0) { + const calloutNode = $from.node(calloutDepth); + if ( + calloutNode.type === this.type && + calloutNode.childCount === 1 && + calloutNode.firstChild?.content.size === 0 + ) { + const calloutPos = $from.before(calloutDepth); + const { tr } = state; + tr.delete(calloutPos, calloutPos + calloutNode.nodeSize); + tr.setSelection( + TextSelection.near(tr.doc.resolve(calloutPos), -1), + ); + view.dispatch(tr); + return true; + } + } + const previousPosition = $from.before($from.depth) - 1; // If nothing above to join with @@ -207,6 +229,56 @@ export const Callout = Node.create({ } return false; }, + + // Exit the callout into a fresh paragraph below when the cursor sits + // in an empty trailing child. An empty callout (single empty + // paragraph) exits on the first Enter and keeps the empty callout + // intact; a callout with content needs the double-Enter pattern + // (first Enter splits, second Enter on the new trailing empty exits + // and removes that trailing paragraph). + Enter: ({ editor }) => { + const { state, view } = editor; + const { selection } = state; + if (!selection.empty) return false; + + const { $from } = selection; + const calloutDepth = $from.depth - 1; + if (calloutDepth < 0) return false; + + const calloutNode = $from.node(calloutDepth); + if (calloutNode.type !== this.type) return false; + if ($from.parent.content.size !== 0) return false; + if ($from.index(calloutDepth) !== calloutNode.childCount - 1) { + return false; + } + + const paragraphType = state.schema.nodes.paragraph; + const containerDepth = calloutDepth - 1; + const container = $from.node(containerDepth); + const indexAfter = $from.indexAfter(containerDepth); + if ( + !container.canReplaceWith(indexAfter, indexAfter, paragraphType) + ) { + return false; + } + + const calloutEnd = $from.after(calloutDepth); + const paragraph = paragraphType.create(); + const { tr } = state; + + if (calloutNode.childCount === 1) { + tr.insert(calloutEnd, paragraph); + tr.setSelection(TextSelection.create(tr.doc, calloutEnd + 1)); + } else { + tr.delete($from.before(), $from.after()); + const insertPos = tr.mapping.map(calloutEnd); + tr.insert(insertPos, paragraph); + tr.setSelection(TextSelection.create(tr.doc, insertPos + 1)); + } + + view.dispatch(tr); + return true; + }, }; }, diff --git a/packages/editor-ext/src/lib/custom-code-block/custom-code-block.ts b/packages/editor-ext/src/lib/custom-code-block/custom-code-block.ts index 4c4b6ef77..5d67188a3 100644 --- a/packages/editor-ext/src/lib/custom-code-block/custom-code-block.ts +++ b/packages/editor-ext/src/lib/custom-code-block/custom-code-block.ts @@ -1,5 +1,7 @@ import type { CodeBlockOptions } from '@tiptap/extension-code-block'; import CodeBlock from '@tiptap/extension-code-block'; +import { Plugin, Selection, TextSelection } from '@tiptap/pm/state'; +import { GapCursor } from '@tiptap/pm/gapcursor'; import { LowlightPlugin } from './lowlight-plugin.js'; import { ReactNodeViewRenderer } from '@tiptap/react'; @@ -19,7 +21,11 @@ const TAB_CHAR = '\u00A0\u00A0'; * @see https://tiptap.dev/api/nodes/code-block-lowlight */ export const CustomCodeBlock = CodeBlock.extend({ + // Run ahead of Gapcursor (100) so the mermaid arrow-into-source plugin + // can intercept before gapcursor takes over. + priority: 101, selectable: true, + isolating: true, addOptions() { return { @@ -35,8 +41,86 @@ export const CustomCodeBlock = CodeBlock.extend({ }, addKeyboardShortcuts() { + const isMermaid = (node: any) => + node?.type === this.type && node.attrs.language === 'mermaid'; + return { ...this.parent?.(), + // Stop at the gap (or enter mermaid source) instead of jumping + // straight into the next block, so the user can place a cursor + // between two adjacent isolating blocks. + ArrowDown: ({ editor }) => { + const { state } = editor; + const { selection, doc } = state; + const { $from, empty } = selection; + + if (!empty || $from.parent.type !== this.type) return false; + if ($from.parentOffset !== $from.parent.nodeSize - 2) return false; + + const after = $from.after(); + if (after >= doc.content.size) { + return editor.commands.exitCode(); + } + + const $after = doc.resolve(after); + const nodeAfter = $after.nodeAfter; + + if (isMermaid(nodeAfter)) { + return editor.commands.command(({ tr }) => { + tr.setSelection(TextSelection.create(tr.doc, after + 1)); + return true; + }); + } + + if ( + nodeAfter?.type.spec.isolating && + !nodeAfter.type.spec.atom + ) { + return editor.commands.command(({ tr }) => { + tr.setSelection(new GapCursor(tr.doc.resolve(after))); + return true; + }); + } + + return editor.commands.command(({ tr }) => { + tr.setSelection(Selection.near(tr.doc.resolve(after))); + return true; + }); + }, + // Mirror of ArrowDown; upstream has no ArrowUp handler. + ArrowUp: ({ editor }) => { + const { state } = editor; + const { selection, doc } = state; + const { $from, empty } = selection; + + if (!empty || $from.parent.type !== this.type) return false; + if ($from.parentOffset !== 0) return false; + + const before = $from.before(); + if (before <= 0) return false; + + const $before = doc.resolve(before); + const nodeBefore = $before.nodeBefore; + + if (isMermaid(nodeBefore)) { + return editor.commands.command(({ tr }) => { + tr.setSelection(TextSelection.create(tr.doc, before - 1)); + return true; + }); + } + + if ( + nodeBefore?.type.spec.isolating && + !nodeBefore.type.spec.atom + ) { + return editor.commands.command(({ tr }) => { + tr.setSelection(new GapCursor(tr.doc.resolve(before))); + return true; + }); + } + + return false; + }, 'Mod-a': () => { if (this.editor.isActive('codeBlock')) { const { state } = this.editor; @@ -84,6 +168,7 @@ export const CustomCodeBlock = CodeBlock.extend({ }, addProseMirrorPlugins() { + const codeBlockType = this.type; return [ ...(this.parent?.() || []), LowlightPlugin({ @@ -91,6 +176,60 @@ export const CustomCodeBlock = CodeBlock.extend({ lowlight: this.options.lowlight, defaultLanguage: this.options.defaultLanguage, }), + // Mermaid hides its
 when unselected, so the browser's native
+      // vertical caret movement skips past it. Land the cursor inside the
+      // source explicitly.
+      new Plugin({
+        props: {
+          handleKeyDown: (view, event) => {
+            if (event.key !== 'ArrowUp' && event.key !== 'ArrowDown') {
+              return false;
+            }
+            const { state } = view;
+            const { selection } = state;
+            if (
+              !selection.empty ||
+              !(selection instanceof TextSelection)
+            ) {
+              return false;
+            }
+            const { $from } = selection;
+            if ($from.depth === 0 || $from.parent.type === codeBlockType) {
+              return false;
+            }
+            const dir = event.key === 'ArrowUp' ? 'up' : 'down';
+            if (!view.endOfTextblock(dir)) return false;
+
+            const isMermaid = (node: any) =>
+              node?.type === codeBlockType && node.attrs.language === 'mermaid';
+
+            if (event.key === 'ArrowUp') {
+              if ($from.parentOffset !== 0) return false;
+              const beforePos = $from.before();
+              const prev = state.doc.resolve(beforePos).nodeBefore;
+              if (!isMermaid(prev)) return false;
+              const endPos = beforePos - 1;
+              view.dispatch(
+                state.tr.setSelection(
+                  TextSelection.create(state.doc, endPos),
+                ),
+              );
+              return true;
+            }
+            if ($from.parentOffset !== $from.parent.nodeSize - 2) return false;
+            const afterPos = $from.after();
+            const next = state.doc.resolve(afterPos).nodeAfter;
+            if (!isMermaid(next)) return false;
+            const startPos = afterPos + 1;
+            view.dispatch(
+              state.tr.setSelection(
+                TextSelection.create(state.doc, startPos),
+              ),
+            );
+            return true;
+          },
+        },
+      }),
     ];
   },
 });
diff --git a/packages/editor-ext/src/lib/utils.ts b/packages/editor-ext/src/lib/utils.ts
index 3bfd01778..8d03577c7 100644
--- a/packages/editor-ext/src/lib/utils.ts
+++ b/packages/editor-ext/src/lib/utils.ts
@@ -338,6 +338,15 @@ export const isRowGripSelected = ({
   return !!gripRow;
 };
 
+// TipTap's `editor.view` proxy throws if accessed before mount or after destroy.
+// Guard floating-menu callbacks (getReferencedVirtualElement, shouldShow) with
+// this before touching `editor.view.nodeDOM(...)`.
+export function isEditorReady(
+  editor: Editor | null | undefined,
+): editor is Editor {
+  return !!editor && editor.isInitialized;
+}
+
 export function isTextSelected(editor: Editor) {
   const {
     state: {

From 0d6538ab1a38fe395827b737570130486f9e14c7 Mon Sep 17 00:00:00 2001
From: Philipinho <16838612+Philipinho@users.noreply.github.com>
Date: Mon, 18 May 2026 22:02:31 +0100
Subject: [PATCH 47/63] feat: iframe configuration

---
 .env.example                                  |  7 ++++++
 apps/server/src/common/helpers/index.ts       |  1 +
 .../src/common/helpers/security-headers.ts    | 19 +++++++++++++++
 .../environment/environment.service.ts        | 15 ++++++++++++
 apps/server/src/main.ts                       | 24 +++++++++++++++++++
 5 files changed, 66 insertions(+)
 create mode 100644 apps/server/src/common/helpers/security-headers.ts

diff --git a/.env.example b/.env.example
index b218bdb84..cf2dafc1d 100644
--- a/.env.example
+++ b/.env.example
@@ -48,6 +48,13 @@ GOTENBERG_URL=
 
 DISABLE_TELEMETRY=false
 
+# Allow other sites to embed Docmost in an iframe.
+IFRAME_EMBED_ALLOWED=false
+
+# Only used when IFRAME_EMBED_ALLOWED=true. When empty, any origin is allowed.
+# Example: https://intranet.example.com,https://portal.example.com
+IFRAME_ALLOWED_ORIGINS=
+
 # Enable debug logging in production (default: false)
 DEBUG_MODE=false
 
diff --git a/apps/server/src/common/helpers/index.ts b/apps/server/src/common/helpers/index.ts
index 13e44d526..80e9a9028 100644
--- a/apps/server/src/common/helpers/index.ts
+++ b/apps/server/src/common/helpers/index.ts
@@ -2,3 +2,4 @@ export * from './utils';
 export * from './nanoid.utils';
 export * from './file.helper';
 export * from './constants';
+export * from './security-headers';
diff --git a/apps/server/src/common/helpers/security-headers.ts b/apps/server/src/common/helpers/security-headers.ts
new file mode 100644
index 000000000..931300e2d
--- /dev/null
+++ b/apps/server/src/common/helpers/security-headers.ts
@@ -0,0 +1,19 @@
+export type SecurityHeader = { name: string; value: string };
+
+export function resolveFrameHeader(
+  iframeEmbedAllowed: boolean,
+  allowedOrigins: string[],
+): SecurityHeader | null {
+  if (!iframeEmbedAllowed) {
+    return { name: 'X-Frame-Options', value: 'SAMEORIGIN' };
+  }
+
+  if (allowedOrigins.length === 0) {
+    return null;
+  }
+
+  return {
+    name: 'Content-Security-Policy',
+    value: `frame-ancestors 'self' ${allowedOrigins.join(' ')}`,
+  };
+}
diff --git a/apps/server/src/integrations/environment/environment.service.ts b/apps/server/src/integrations/environment/environment.service.ts
index abee1966f..20824d355 100644
--- a/apps/server/src/integrations/environment/environment.service.ts
+++ b/apps/server/src/integrations/environment/environment.service.ts
@@ -325,4 +325,19 @@ export class EnvironmentService {
       .toLowerCase();
     return disabled === 'true';
   }
+
+  isIframeEmbedAllowed(): boolean {
+    const allowed = this.configService
+      .get('IFRAME_EMBED_ALLOWED', 'false')
+      .toLowerCase();
+    return allowed === 'true';
+  }
+
+  getIframeAllowedOrigins(): string[] {
+    const raw = this.configService.get('IFRAME_ALLOWED_ORIGINS', '');
+    return raw
+      .split(',')
+      .map((o) => o.trim())
+      .filter(Boolean);
+  }
 }
diff --git a/apps/server/src/main.ts b/apps/server/src/main.ts
index 877411223..1c2ccebf1 100644
--- a/apps/server/src/main.ts
+++ b/apps/server/src/main.ts
@@ -12,6 +12,8 @@ import fastifyMultipart from '@fastify/multipart';
 import fastifyCookie from '@fastify/cookie';
 import fastifyIp from 'fastify-ip';
 import { InternalLogFilter } from './common/logger/internal-log-filter';
+import { EnvironmentService } from './integrations/environment/environment.service';
+import { resolveFrameHeader } from './common/helpers';
 
 async function bootstrap() {
   const app = await NestFactory.create(
@@ -50,6 +52,28 @@ async function bootstrap() {
   await app.register(fastifyMultipart);
   await app.register(fastifyCookie);
 
+  const environmentService = app.get(EnvironmentService);
+  const frameHeader = resolveFrameHeader(
+    environmentService.isIframeEmbedAllowed(),
+    environmentService.getIframeAllowedOrigins(),
+  );
+  if (frameHeader) {
+    // Skipped routes:
+    //   /api/files/ - attachment controller sets its own CSP we'd overwrite
+    //   /share/     0 public share pages are safe to embed
+    const frameHeaderSkippedPrefixes = ['/api/files/', '/share/'];
+    app
+      .getHttpAdapter()
+      .getInstance()
+      .addHook('onSend', (req, reply, payload, done) => {
+        if (frameHeaderSkippedPrefixes.some((p) => req.url.startsWith(p))) {
+          return done(null, payload);
+        }
+        reply.header(frameHeader.name, frameHeader.value);
+        done(null, payload);
+      });
+  }
+
   app
     .getHttpAdapter()
     .getInstance()

From 6cf8101ab3661c00e1b960739377d4c2bb71e73d Mon Sep 17 00:00:00 2001
From: Philip Okugbe <16838612+Philipinho@users.noreply.github.com>
Date: Tue, 19 May 2026 02:41:52 +0100
Subject: [PATCH 48/63] feat(ee): templates (#2215)

* feat(ee): templates
* fix tree
* fix
---
 .../public/locales/en-US/translation.json     |  29 ++
 .../layouts/global/global-sidebar.module.css  |  10 +
 .../layouts/global/global-sidebar.tsx         |  68 +++--
 .../destination-picker-modal.tsx              |   4 +
 .../destination-picker.module.css             |  10 +-
 .../destination-picker/destination-picker.tsx |  88 +++++-
 .../destination-picker.types.ts               |   2 +
 .../ui/destination-picker/page-row.tsx        |  44 ++-
 .../ui/destination-picker/space-row.tsx       |  32 ++-
 .../components/allow-member-templates.tsx     |  10 +-
 .../client/src/ee/security/pages/security.tsx |   1 -
 .../components/template-card.module.css       |  20 +-
 .../ee/template/components/template-card.tsx  |  28 +-
 .../template-picker-modal.module.css          |  70 +++++
 .../components/template-picker-modal.tsx      | 259 ++++++++++++++++++
 .../components/template-preview-modal.tsx     |  13 +-
 .../components/use-template-modal.tsx         |   4 +
 .../src/ee/template/pages/template-editor.tsx |  12 +
 .../src/ee/template/pages/template-list.tsx   |   3 +-
 .../src/ee/template/queries/template-query.ts |  70 ++++-
 .../ee/template/services/template-service.ts  |   5 +-
 .../features/editor/extensions/extensions.ts  |   4 +-
 .../components/sidebar/space-sidebar.tsx      |  32 +++
 .../settings/workspace/workspace-settings.tsx |   4 +
 .../database/repos/template/template.repo.ts  |   6 +-
 25 files changed, 752 insertions(+), 76 deletions(-)
 create mode 100644 apps/client/src/ee/template/components/template-picker-modal.module.css
 create mode 100644 apps/client/src/ee/template/components/template-picker-modal.tsx

diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json
index d59aa94b9..62927f66a 100644
--- a/apps/client/public/locales/en-US/translation.json
+++ b/apps/client/public/locales/en-US/translation.json
@@ -936,6 +936,35 @@
   "Page actions": "Page actions",
   "Pick emoji": "Pick emoji",
   "Template menu": "Template menu",
+  "Use": "Use",
+  "Use template": "Use template",
+  "Preview template: {{title}}": "Preview template: {{title}}",
+  "Use a template": "Use a template",
+  "Search templates...": "Search templates...",
+  "Search spaces...": "Search spaces...",
+  "No templates found": "No templates found",
+  "No spaces found": "No spaces found",
+  "Browse all templates": "Browse all templates",
+  "This space": "This space",
+  "All templates": "All templates",
+  "Global": "Global",
+  "New template": "New template",
+  "Edit template": "Edit template",
+  "Are you sure you want to delete this template?": "Are you sure you want to delete this template?",
+  "Template scope updated": "Template scope updated",
+  "Choose which space this template belongs to": "Choose which space this template belongs to",
+  "Scope": "Scope",
+  "Select scope": "Select scope",
+  "Title": "Title",
+  "Saving...": "Saving...",
+  "Saved": "Saved",
+  "Save failed. Retry": "Save failed. Retry",
+  "By {{name}}": "By {{name}}",
+  "Updated {{time}}": "Updated {{time}}",
+  "Choose destination": "Choose destination",
+  "Search pages and spaces...": "Search pages and spaces...",
+  "No results found": "No results found",
+  "You don't have permission to create pages here": "You don't have permission to create pages here",
   "Chat menu": "Chat menu",
   "API key menu": "API key menu",
   "Jump to comment selection": "Jump to comment selection",
diff --git a/apps/client/src/components/layouts/global/global-sidebar.module.css b/apps/client/src/components/layouts/global/global-sidebar.module.css
index 9a7bc1b6f..1385ec20d 100644
--- a/apps/client/src/components/layouts/global/global-sidebar.module.css
+++ b/apps/client/src/components/layouts/global/global-sidebar.module.css
@@ -38,6 +38,16 @@
             color: light-dark(var(--mantine-color-black), var(--mantine-color-white));
         }
     }
+
+    &[data-disabled] {
+        cursor: not-allowed;
+        opacity: 0.5;
+
+        @mixin hover {
+            background-color: transparent;
+            color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1));
+        }
+    }
 }
 
 .linkIcon {
diff --git a/apps/client/src/components/layouts/global/global-sidebar.tsx b/apps/client/src/components/layouts/global/global-sidebar.tsx
index 5019d5d98..6882f81d4 100644
--- a/apps/client/src/components/layouts/global/global-sidebar.tsx
+++ b/apps/client/src/components/layouts/global/global-sidebar.tsx
@@ -1,5 +1,5 @@
 import { useEffect, useState } from "react";
-import { ScrollArea, Text, Divider, Modal, UnstyledButton } from "@mantine/core";
+import { ScrollArea, Text, Divider, Modal, UnstyledButton, Tooltip } from "@mantine/core";
 import {
   IconHome,
   IconClock,
@@ -7,6 +7,7 @@ import {
   IconLayoutGrid,
   IconSettings,
   IconUserPlus,
+  IconTemplate,
 } from "@tabler/icons-react";
 import { Link, useLocation } from "react-router-dom";
 import classes from "./global-sidebar.module.css";
@@ -20,12 +21,9 @@ import { useDisclosure } from "@mantine/hooks";
 import { WorkspaceInviteForm } from "@/features/workspace/components/members/components/workspace-invite-form";
 import { CustomAvatar } from "@/components/ui/custom-avatar";
 import { AvatarIconType } from "@/features/attachments/types/attachment.types";
-
-const mainNavItems = [
-  { label: "Home", icon: IconHome, path: "/home" },
-  { label: "Favorites", icon: IconStar, path: "/favorites" },
-  { label: "Spaces", icon: IconLayoutGrid, path: "/spaces" },
-];
+import { useHasFeature } from "@/ee/hooks/use-feature";
+import { Feature } from "@/ee/features";
+import { useUpgradeLabel } from "@/ee/hooks/use-upgrade-label";
 
 export default function GlobalSidebar() {
   const { t } = useTranslation();
@@ -33,6 +31,19 @@ export default function GlobalSidebar() {
   const [active, setActive] = useState(location.pathname);
   const [mobileSidebarOpened] = useAtom(mobileSidebarAtom);
   const toggleMobileSidebar = useToggleSidebar(mobileSidebarAtom);
+  const hasTemplates = useHasFeature(Feature.TEMPLATES);
+  const upgradeLabel = useUpgradeLabel();
+  const mainNavItems = [
+    { label: "Home", icon: IconHome, path: "/home" },
+    { label: "Favorites", icon: IconStar, path: "/favorites" },
+    { label: "Spaces", icon: IconLayoutGrid, path: "/spaces" },
+    {
+      label: "Templates",
+      icon: IconTemplate,
+      path: "/templates",
+      disabled: !hasTemplates,
+    },
+  ];
   const { data: favoriteSpacesData, isPending: isFavoritesPending } = useFavoritesQuery("space");
   const favoriteSpaces = favoriteSpacesData?.pages.flatMap((p) => p.items) ?? [];
   const sortedFavoriteSpaces = [...favoriteSpaces]
@@ -58,18 +69,37 @@ export default function GlobalSidebar() {
     
- {mainNavItems.map((item) => ( - - - {t(item.label)} - - ))} + {mainNavItems.map((item) => + item.disabled ? ( + + + + {t(item.label)} + + + ) : ( + + + {t(item.label)} + + ), + )}
diff --git a/apps/client/src/components/ui/destination-picker/destination-picker-modal.tsx b/apps/client/src/components/ui/destination-picker/destination-picker-modal.tsx index 04e9ef7dd..21c906969 100644 --- a/apps/client/src/components/ui/destination-picker/destination-picker-modal.tsx +++ b/apps/client/src/components/ui/destination-picker/destination-picker-modal.tsx @@ -16,6 +16,8 @@ export function DestinationPickerModal({ loading, excludePageId, pageLimit, + initialSpaceId, + searchSpacesOnly, }: DestinationPickerModalProps) { const { t } = useTranslation(); const [selection, setSelection] = useState(null); @@ -46,6 +48,8 @@ export function DestinationPickerModal({ onSelectionChange={setSelection} excludePageId={excludePageId} pageLimit={pageLimit} + initialSpaceId={initialSpaceId} + searchSpacesOnly={searchSpacesOnly} /> diff --git a/apps/client/src/components/ui/destination-picker/destination-picker.module.css b/apps/client/src/components/ui/destination-picker/destination-picker.module.css index ec598ac50..fb868bc14 100644 --- a/apps/client/src/components/ui/destination-picker/destination-picker.module.css +++ b/apps/client/src/components/ui/destination-picker/destination-picker.module.css @@ -13,6 +13,7 @@ display: flex; align-items: center; gap: 8px; + color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); transition: background-color 150ms ease; user-select: none; @@ -22,6 +23,11 @@ var(--mantine-color-dark-6) ); } + + &:focus-visible { + outline: 2px solid var(--mantine-primary-color-filled); + outline-offset: -2px; + } } .selected { @@ -57,7 +63,7 @@ border-radius: var(--mantine-radius-sm); flex-shrink: 0; transition: transform 150ms ease; - color: light-dark(var(--mantine-color-gray-5), var(--mantine-color-dark-3)); + color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-dark-2)); @mixin hover { background-color: light-dark( @@ -111,7 +117,7 @@ } .spaceName { - color: light-dark(var(--mantine-color-gray-5), var(--mantine-color-dark-3)); + color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-dark-2)); font-size: var(--mantine-font-size-xs); flex-shrink: 0; } diff --git a/apps/client/src/components/ui/destination-picker/destination-picker.tsx b/apps/client/src/components/ui/destination-picker/destination-picker.tsx index 1ddc747dd..b16a25a48 100644 --- a/apps/client/src/components/ui/destination-picker/destination-picker.tsx +++ b/apps/client/src/components/ui/destination-picker/destination-picker.tsx @@ -1,7 +1,7 @@ -import { useState, useCallback } from "react"; -import { TextInput, ScrollArea, Loader } from "@mantine/core"; +import { useState, useCallback, useEffect, useMemo, useRef } from "react"; +import { ActionIcon, TextInput, ScrollArea, Loader } from "@mantine/core"; import { useDebouncedValue } from "@mantine/hooks"; -import { IconSearch, IconFile } from "@tabler/icons-react"; +import { IconSearch, IconFileDescription } from "@tabler/icons-react"; import { useTranslation } from "react-i18next"; import { useGetSpacesQuery } from "@/features/space/queries/space-query"; import { useSearchSuggestionsQuery } from "@/features/search/queries/search-query"; @@ -15,23 +15,29 @@ type DestinationPickerProps = { onSelectionChange: (selection: DestinationSelection | null) => void; excludePageId?: string; pageLimit?: number; + initialSpaceId?: string; + searchSpacesOnly?: boolean; }; export function DestinationPicker({ onSelectionChange, excludePageId, pageLimit = 15, + initialSpaceId, + searchSpacesOnly, }: DestinationPickerProps) { const { t } = useTranslation(); const [searchQuery, setSearchQuery] = useState(""); const [selection, setSelection] = useState(null); const [debouncedQuery] = useDebouncedValue(searchQuery, 300); + const viewportRef = useRef(null); const { data: spacesData, isLoading: spacesLoading } = useGetSpacesQuery({ limit: 100, }); - const searchEnabled = debouncedQuery && debouncedQuery.length >= 2; + const searchEnabled = + !searchSpacesOnly && debouncedQuery && debouncedQuery.length >= 2; const { data: searchData, isLoading: searchLoading } = useSearchSuggestionsQuery({ @@ -42,6 +48,18 @@ export function DestinationPicker({ const isSearching = !!searchEnabled; + const filteredSpaces = useMemo(() => { + const items = spacesData?.items ?? []; + if (!searchSpacesOnly || !debouncedQuery) return items; + const fold = (s: string) => + s + .normalize("NFD") + .replace(/[̀-ͯ]/g, "") + .toLocaleLowerCase(); + const term = fold(debouncedQuery); + return items.filter((s) => fold(s.name).includes(term)); + }, [spacesData, searchSpacesOnly, debouncedQuery]); + const selectedId = selection?.type === "space" ? selection.spaceId : selection?.pageId ?? null; @@ -87,18 +105,48 @@ export function DestinationPicker({ [updateSelection], ); + // Pre-select space when initialSpaceId is set and spaces have loaded. + // Only runs once: skip if user has already made a selection. + useEffect(() => { + if (!initialSpaceId || selection) return; + const match = spacesData?.items?.find((s) => s.id === initialSpaceId); + if (match) { + updateSelection({ type: "space", spaceId: match.id, space: match }); + requestAnimationFrame(() => { + const el = viewportRef.current?.querySelector( + `[data-space-id="${match.id}"]`, + ); + el?.scrollIntoView({ block: "nearest" }); + }); + } + }, [initialSpaceId, selection, spacesData, updateSelection]); + return ( <> } - placeholder={t("Search pages and spaces...")} + placeholder={ + searchSpacesOnly + ? t("Search spaces...") + : t("Search pages and spaces...") + } + aria-label={ + searchSpacesOnly + ? t("Search spaces...") + : t("Search pages and spaces...") + } variant="filled" value={searchQuery} onChange={(e) => setSearchQuery(e.currentTarget.value)} className={classes.searchInput} /> - + {isSearching ? ( searchLoading ? (
@@ -111,16 +159,28 @@ export function DestinationPicker({
handleSearchResultClick(page)} + onKeyDown={(e) => { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + handleSearchResultClick(page); + } + }} >
{page.icon ? ( page.icon ) : ( - + + + )}
@@ -141,8 +201,14 @@ export function DestinationPicker({
+ ) : filteredSpaces.length === 0 ? ( +
+ {searchSpacesOnly && debouncedQuery + ? t("No spaces found") + : t("No results found")} +
) : ( - spacesData?.items?.map((space) => ( + filteredSpaces.map((space) => ( { + if (!isExcluded) onSelect(page); + }; + + const handleRowKeyDown = (e: KeyboardEvent) => { + if (e.target !== e.currentTarget) return; + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + handleSelect(); + } + }; + return ( <>
!isExcluded && onSelect(page)} + role="button" + tabIndex={isExcluded ? -1 : 0} + aria-disabled={isExcluded || undefined} + onClick={handleSelect} + onKeyDown={handleRowKeyDown} > {page.hasChildren ? ( -
{ e.stopPropagation(); setExpanded(!expanded); }} > -
+ ) : (
)} @@ -61,10 +83,14 @@ export function PageRow({ {page.icon ? ( page.icon ) : ( - + + + )}
diff --git a/apps/client/src/components/ui/destination-picker/space-row.tsx b/apps/client/src/components/ui/destination-picker/space-row.tsx index 59273af7e..857f18f6c 100644 --- a/apps/client/src/components/ui/destination-picker/space-row.tsx +++ b/apps/client/src/components/ui/destination-picker/space-row.tsx @@ -1,5 +1,5 @@ -import { useState } from "react"; -import { Tooltip } from "@mantine/core"; +import { KeyboardEvent, useState } from "react"; +import { ActionIcon, Tooltip } from "@mantine/core"; import { IconChevronRight, IconLock } from "@tabler/icons-react"; import { useTranslation } from "react-i18next"; import { ISpace } from "@/features/space/types/space.types"; @@ -42,21 +42,43 @@ export function SpaceRow({ .filter(Boolean) .join(" "); + const handleSelect = () => { + if (writable) onSelectSpace(space); + }; + + const handleRowKeyDown = (e: KeyboardEvent) => { + if (e.target !== e.currentTarget) return; + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + handleSelect(); + } + }; + const rowContent = (
writable && onSelectSpace(space)} + data-space-id={space.id} + role="button" + tabIndex={writable ? 0 : -1} + aria-disabled={!writable || undefined} + onClick={handleSelect} + onKeyDown={handleRowKeyDown} > {writable ? ( -
{ e.stopPropagation(); setExpanded(!expanded); }} > -
+ ) : (
)} diff --git a/apps/client/src/ee/security/components/allow-member-templates.tsx b/apps/client/src/ee/security/components/allow-member-templates.tsx index f547d1644..8acc8ba6d 100644 --- a/apps/client/src/ee/security/components/allow-member-templates.tsx +++ b/apps/client/src/ee/security/components/allow-member-templates.tsx @@ -34,7 +34,7 @@ function AllowMemberTemplatesToggle() { const [checked, setChecked] = useState( workspace?.settings?.templates?.allowMemberTemplates === true, ); - const hasSecuritySettings = useHasFeature(Feature.SECURITY_SETTINGS); + const hasTemplates = useHasFeature(Feature.TEMPLATES); const upgradeLabel = useUpgradeLabel(); const handleChange = async (event: React.ChangeEvent) => { @@ -54,15 +54,11 @@ function AllowMemberTemplatesToggle() { }; return ( - + diff --git a/apps/client/src/ee/security/pages/security.tsx b/apps/client/src/ee/security/pages/security.tsx index ee6343516..2ff3670be 100644 --- a/apps/client/src/ee/security/pages/security.tsx +++ b/apps/client/src/ee/security/pages/security.tsx @@ -137,7 +137,6 @@ export default function Security() { { max: SCIM_TOKEN_LIMIT }, )} disabled={(scimData?.items.length ?? 0) < SCIM_TOKEN_LIMIT} - refProp="rootRef" > {canManage && ( @@ -91,6 +114,7 @@ export default function TemplateCard({
{template.title}
+
diff --git a/apps/client/src/features/group/components/group-members.tsx b/apps/client/src/features/group/components/group-members.tsx index 56807bf8d..14c5903a7 100644 --- a/apps/client/src/features/group/components/group-members.tsx +++ b/apps/client/src/features/group/components/group-members.tsx @@ -88,7 +88,11 @@ export default function GroupMembersList() { arrowPosition="center" > - + diff --git a/apps/client/src/features/home/components/created-by-me.tsx b/apps/client/src/features/home/components/created-by-me.tsx index 99051357e..bc79da994 100644 --- a/apps/client/src/features/home/components/created-by-me.tsx +++ b/apps/client/src/features/home/components/created-by-me.tsx @@ -17,6 +17,7 @@ import { EmptyState } from "@/components/ui/empty-state"; import { getSpaceUrl } from "@/lib/config"; import { useTranslation } from "react-i18next"; import { getInitialsColor } from "@/lib/get-initials-color"; +import rowClasses from "@/components/ui/clickable-table-row.module.css"; type Props = { spaceId?: string; @@ -49,9 +50,10 @@ export default function CreatedByMe({ spaceId }: Props) { {pages.map((page) => ( - + {favorites.map((fav) => fav.page ? ( - + ("direct"); const [filter, setFilter] = useState("all"); + const [filterMenuOpened, setFilterMenuOpened] = useState(false); + const [moreMenuOpened, setMoreMenuOpened] = useState(false); const { data: unreadData } = useUnreadCountQuery(); const markAllRead = useMarkAllReadMutation(); const unreadCount = unreadData?.count ?? 0; + const isSubMenuOpen = filterMenuOpened || moreMenuOpened; const handleMarkAllRead = () => { markAllRead.mutate(); @@ -51,6 +54,9 @@ export function NotificationPopover() { opened={opened} onChange={setOpened} withArrow + trapFocus + returnFocus + closeOnEscape={!isSubMenuOpen} > @@ -80,14 +86,25 @@ export function NotificationPopover() { style={{ width: "min(420px, calc(100vw - 24px))" }} > - + {t("Notifications")} - </Text> + - + - + @@ -113,10 +130,21 @@ export function NotificationPopover() { - + - + diff --git a/apps/client/src/features/page-details/components/backlinks-modal.tsx b/apps/client/src/features/page-details/components/backlinks-modal.tsx index 83fc31147..1fbd771a3 100644 --- a/apps/client/src/features/page-details/components/backlinks-modal.tsx +++ b/apps/client/src/features/page-details/components/backlinks-modal.tsx @@ -23,7 +23,7 @@ export function BacklinksModal({ {t("Backlinks")} - + diff --git a/apps/client/src/features/page-history/components/history-modal.tsx b/apps/client/src/features/page-history/components/history-modal.tsx index 08f05c9e9..05768638a 100644 --- a/apps/client/src/features/page-history/components/history-modal.tsx +++ b/apps/client/src/features/page-history/components/history-modal.tsx @@ -32,7 +32,7 @@ export default function HistoryModal({ pageId, pageTitle }: Props) { {t("Page history")} - + - + diff --git a/apps/client/src/features/page/components/copy-page-modal.tsx b/apps/client/src/features/page/components/copy-page-modal.tsx index 4745f731c..b03bd1e5e 100644 --- a/apps/client/src/features/page/components/copy-page-modal.tsx +++ b/apps/client/src/features/page/components/copy-page-modal.tsx @@ -80,7 +80,7 @@ export default function CopyPageModal({ {t("Copy page")} - + diff --git a/apps/client/src/features/page/components/header/page-header-menu.tsx b/apps/client/src/features/page/components/header/page-header-menu.tsx index 75b113eaa..d82cb494c 100644 --- a/apps/client/src/features/page/components/header/page-header-menu.tsx +++ b/apps/client/src/features/page/components/header/page-header-menu.tsx @@ -18,7 +18,7 @@ import { IconWifiOff, } from "@tabler/icons-react"; import React, { useEffect, useRef, useState } from "react"; -import useToggleAside from "@/hooks/use-toggle-aside.tsx"; +import { useAsideTriggerProps } from "@/hooks/use-toggle-aside.tsx"; import { useAtom, useAtomValue } from "jotai"; import { historyAtoms } from "@/features/page-history/atoms/history-atoms.ts"; import { useDisclosure, useHotkeys } from "@mantine/hooks"; @@ -64,7 +64,8 @@ interface PageHeaderMenuProps { } export default function PageHeaderMenu({ readOnly }: PageHeaderMenuProps) { const { t } = useTranslation(); - const toggleAside = useToggleAside(); + const commentsTriggerProps = useAsideTriggerProps("comments"); + const tocTriggerProps = useAsideTriggerProps("toc"); const { pageSlug } = useParams(); const { data: page } = usePageQuery({ pageId: extractPageSlugId(pageSlug), @@ -109,7 +110,7 @@ export default function PageHeaderMenu({ readOnly }: PageHeaderMenuProps) { variant="subtle" color="dark" aria-label={t("Comments")} - onClick={() => toggleAside("comments")} + {...commentsTriggerProps} > @@ -120,7 +121,7 @@ export default function PageHeaderMenu({ readOnly }: PageHeaderMenuProps) { variant="subtle" color="dark" aria-label={t("Table of contents")} - onClick={() => toggleAside("toc")} + {...tocTriggerProps} > diff --git a/apps/client/src/features/page/components/move-page-modal.tsx b/apps/client/src/features/page/components/move-page-modal.tsx index 74880084b..907bea2f2 100644 --- a/apps/client/src/features/page/components/move-page-modal.tsx +++ b/apps/client/src/features/page/components/move-page-modal.tsx @@ -75,7 +75,7 @@ export default function MovePageModal({ {t("Move page")} - + diff --git a/apps/client/src/features/page/trash/components/trash-page-content-modal.tsx b/apps/client/src/features/page/trash/components/trash-page-content-modal.tsx index c9aad622c..842c4257c 100644 --- a/apps/client/src/features/page/trash/components/trash-page-content-modal.tsx +++ b/apps/client/src/features/page/trash/components/trash-page-content-modal.tsx @@ -28,7 +28,7 @@ export default function TrashPageContentModal({ {t("Preview")} - + diff --git a/apps/client/src/features/page/trash/components/trash.tsx b/apps/client/src/features/page/trash/components/trash.tsx index da33d828f..2b5ca9649 100644 --- a/apps/client/src/features/page/trash/components/trash.tsx +++ b/apps/client/src/features/page/trash/components/trash.tsx @@ -150,7 +150,11 @@ export default function Trash() { - + diff --git a/apps/client/src/features/page/tree/components/space-tree-node-menu.tsx b/apps/client/src/features/page/tree/components/space-tree-node-menu.tsx index 91a21b052..27b0ce210 100644 --- a/apps/client/src/features/page/tree/components/space-tree-node-menu.tsx +++ b/apps/client/src/features/page/tree/components/space-tree-node-menu.tsx @@ -125,7 +125,7 @@ export function NodeMenu({ node, canEdit }: NodeMenuProps) { { e.preventDefault(); diff --git a/apps/client/src/features/page/tree/components/space-tree-row.tsx b/apps/client/src/features/page/tree/components/space-tree-row.tsx index 1ed148350..3da690066 100644 --- a/apps/client/src/features/page/tree/components/space-tree-row.tsx +++ b/apps/client/src/features/page/tree/components/space-tree-row.tsx @@ -274,7 +274,7 @@ function CreateNode({ { e.preventDefault(); diff --git a/apps/client/src/features/search/components/search-spotlight-filters.tsx b/apps/client/src/features/search/components/search-spotlight-filters.tsx index 4502c755a..d41bef7e7 100644 --- a/apps/client/src/features/search/components/search-spotlight-filters.tsx +++ b/apps/client/src/features/search/components/search-spotlight-filters.tsx @@ -175,6 +175,8 @@ export function SearchSpotlightFilters({ {contentTypeOptions.map((option) => ( !option.disabled && contentType !== option.value && @@ -200,7 +202,7 @@ export function SearchSpotlightFilters({ )} - {contentType === option.value && } + {contentType === option.value && } ))} diff --git a/apps/client/src/features/search/components/search-spotlight.tsx b/apps/client/src/features/search/components/search-spotlight.tsx index 5a2980a38..4c5269f15 100644 --- a/apps/client/src/features/search/components/search-spotlight.tsx +++ b/apps/client/src/features/search/components/search-spotlight.tsx @@ -1,6 +1,6 @@ import { Spotlight } from "@mantine/spotlight"; import { IconSearch, IconSparkles } from "@tabler/icons-react"; -import { Group, Button } from "@mantine/core"; +import { Group, Button, VisuallyHidden } from "@mantine/core"; import React, { useState, useMemo, useEffect } from "react"; import { useDebouncedValue } from "@mantine/hooks"; import { useTranslation } from "react-i18next"; @@ -126,6 +126,7 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) { } style={{ flex: 1 }} onKeyDown={(e) => { @@ -161,6 +162,18 @@ export function SearchSpotlight({ spaceId }: SearchSpotlightProps) { /> + + {isAiMode + ? query.length > 0 && !isAiLoading && !aiSearchResult + ? t("No answer available") + : "" + : query.length > 0 && !isLoading + ? resultItems.length === 0 + ? t("No results found") + : t("{{count}} results found", { count: resultItems.length }) + : ""} + + {isAiMode ? ( <> diff --git a/apps/client/src/features/search/components/share-search-spotlight.tsx b/apps/client/src/features/search/components/share-search-spotlight.tsx index dd0d5181f..eccaeb4db 100644 --- a/apps/client/src/features/search/components/share-search-spotlight.tsx +++ b/apps/client/src/features/search/components/share-search-spotlight.tsx @@ -74,6 +74,7 @@ export function ShareSearchSpotlight({ shareId }: ShareSearchSpotlightProps) { > } /> diff --git a/apps/client/src/features/session/components/session-list.tsx b/apps/client/src/features/session/components/session-list.tsx index 6549a6e5f..9e519942c 100644 --- a/apps/client/src/features/session/components/session-list.tsx +++ b/apps/client/src/features/session/components/session-list.tsx @@ -7,6 +7,7 @@ import { Stack, Table, Text, + VisuallyHidden, } from "@mantine/core"; import { IconDevices } from "@tabler/icons-react"; import { useTranslation } from "react-i18next"; @@ -33,11 +34,16 @@ export default function SessionList() { if (isLoading) { return (
+ + {t("Active sessions")} + {t("Device Name")} {t("Last Active")} - + + {t("Action")} + @@ -90,11 +96,18 @@ export default function SessionList() { )}
+ + {t("Active sessions")} + {t("Device Name")} {t("Last Active")} - {otherSessions.length > 0 && } + {otherSessions.length > 0 && ( + + {t("Action")} + + )} diff --git a/apps/client/src/features/share/components/share-list.tsx b/apps/client/src/features/share/components/share-list.tsx index 147c8bb90..37ea4abf6 100644 --- a/apps/client/src/features/share/components/share-list.tsx +++ b/apps/client/src/features/share/components/share-list.tsx @@ -14,6 +14,7 @@ import { getPageIcon } from "@/lib"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx"; import { EmptyState } from "@/components/ui/empty-state.tsx"; import classes from "./share.module.css"; +import rowClasses from "@/components/ui/clickable-table-row.module.css"; export default function ShareList() { const { t } = useTranslation(); @@ -38,7 +39,7 @@ export default function ShareList() { {data?.items.map((share: ISharedItem, index: number) => ( - + + + 1 && { navbar: { @@ -242,7 +245,7 @@ export default function ShareShell({ )} - + {children} {data && shareId && !(data.features?.length > 0) && } @@ -264,5 +267,6 @@ export default function ShareShell({ + ); } diff --git a/apps/client/src/features/space/components/add-space-members-modal.tsx b/apps/client/src/features/space/components/add-space-members-modal.tsx index 5efd32f6b..79910ae3a 100644 --- a/apps/client/src/features/space/components/add-space-members-modal.tsx +++ b/apps/client/src/features/space/components/add-space-members-modal.tsx @@ -1,6 +1,6 @@ import { Button, Divider, Group, Modal, Stack } from "@mantine/core"; import { useDisclosure } from "@mantine/hooks"; -import React, { useState } from "react"; +import React, { useId, useState } from "react"; import { useAddSpaceMemberMutation } from "@/features/space/queries/space-query.ts"; import { MultiMemberSelect } from "@/features/space/components/multi-member-select.tsx"; import { SpaceMemberRole } from "@/features/space/components/space-member-role.tsx"; @@ -14,6 +14,7 @@ export default function AddSpaceMembersModal({ spaceId, }: AddSpaceMemberModalProps) { const { t } = useTranslation(); + const titleId = useId(); const [opened, { open, close }] = useDisclosure(false); const [memberIds, setMemberIds] = useState([]); const [role, setRole] = useState(SpaceRole.WRITER); @@ -51,24 +52,33 @@ export default function AddSpaceMembersModal({ return ( <> - - + + + + + {t("Add space members")} + + + + - - - - + + + + - - - - + + + + + + ); } diff --git a/apps/client/src/features/space/components/create-space-form.tsx b/apps/client/src/features/space/components/create-space-form.tsx index 896b599b3..d5d26d57b 100644 --- a/apps/client/src/features/space/components/create-space-form.tsx +++ b/apps/client/src/features/space/components/create-space-form.tsx @@ -1,4 +1,4 @@ -import { Group, Box, Button, TextInput, Stack, Textarea } from "@mantine/core"; +import { Group, Box, Button, TextInput, Stack, Textarea, Text } from "@mantine/core"; import React, { useEffect } from "react"; import { useForm } from "@mantine/form"; import { zod4Resolver } from "mantine-form-zod-resolver"; @@ -69,10 +69,25 @@ export function CreateSpaceForm() { navigate(getSpaceUrl(createdSpace.slug)); }; + function handleValidationFailure(errors: Record) { + const firstInvalidId = Object.keys(errors)[0]; + if (firstInvalidId) { + document.getElementById(firstInvalidId)?.focus(); + } + } + return ( <> -
handleSubmit(values))}> + handleSubmit(values), + handleValidationFailure, + )} + > + + {t("* indicates required fields")} + @@ -89,6 +106,7 @@ export function CreateSpaceForm() { label={t("Space slug")} placeholder={t("e.g product")} variant="filled" + errorProps={{ role: "alert" }} {...form.getInputProps("slug")} /> @@ -100,6 +118,7 @@ export function CreateSpaceForm() { autosize minRows={2} maxRows={8} + errorProps={{ role: "alert" }} {...form.getInputProps("description")} /> diff --git a/apps/client/src/features/space/components/create-space-modal.tsx b/apps/client/src/features/space/components/create-space-modal.tsx index 152e1950c..22f3e40c3 100644 --- a/apps/client/src/features/space/components/create-space-modal.tsx +++ b/apps/client/src/features/space/components/create-space-modal.tsx @@ -11,7 +11,12 @@ export default function CreateSpaceModal() { <> - + diff --git a/apps/client/src/features/space/components/settings-modal.tsx b/apps/client/src/features/space/components/settings-modal.tsx index fb8d24f63..3d24d100c 100644 --- a/apps/client/src/features/space/components/settings-modal.tsx +++ b/apps/client/src/features/space/components/settings-modal.tsx @@ -48,7 +48,7 @@ export default function SpaceSettingsModal({ {space?.name} - +
diff --git a/apps/client/src/features/space/components/sidebar/switch-space.tsx b/apps/client/src/features/space/components/sidebar/switch-space.tsx index 89e0f64ee..7531a5926 100644 --- a/apps/client/src/features/space/components/sidebar/switch-space.tsx +++ b/apps/client/src/features/space/components/sidebar/switch-space.tsx @@ -38,6 +38,8 @@ export function SwitchSpace({ shadow="md" opened={opened} onChange={toggle} + trapFocus + returnFocus >
+ + + {t("List of spaces in this workspace")} + + {t("Space")} {t("Members")} - + + {t("Action")} + {spaces.length > 0 ? ( spaces.map((space) => ( - + prefetchSpace(space.slug, space.id)} > - + diff --git a/apps/client/src/features/space/components/spaces-page/favorite-spaces-grid.tsx b/apps/client/src/features/space/components/spaces-page/favorite-spaces-grid.tsx index 131de2995..a2a2ec263 100644 --- a/apps/client/src/features/space/components/spaces-page/favorite-spaces-grid.tsx +++ b/apps/client/src/features/space/components/spaces-page/favorite-spaces-grid.tsx @@ -1,4 +1,4 @@ -import { Text, SimpleGrid, Card, rem, Group, Box, Button } from "@mantine/core"; +import { Text, SimpleGrid, Card, rem, Group, Box, Button, Title } from "@mantine/core"; import { useState } from "react"; import { Link } from "react-router-dom"; import { useTranslation } from "react-i18next"; @@ -30,9 +30,9 @@ export default function FavoriteSpacesGrid() { return ( - + {t("Favorite spaces")} - </Text> + {visibleSpaces.map((fav) => ( @@ -53,6 +53,7 @@ export default function FavoriteSpacesGrid() { diff --git a/apps/client/src/features/user/components/change-email.tsx b/apps/client/src/features/user/components/change-email.tsx index 16f74b427..8c841b401 100644 --- a/apps/client/src/features/user/components/change-email.tsx +++ b/apps/client/src/features/user/components/change-email.tsx @@ -36,7 +36,13 @@ export default function ChangeEmail() { */} - + {t( "To change your email, you have to enter your password and new email.", @@ -80,6 +86,11 @@ function ChangeEmailForm() { placeholder={t("Enter your password")} variant="filled" mb="md" + visibilityToggleButtonProps={{ + "aria-label": t("Toggle password visibility"), + "aria-hidden": false, + tabIndex: 0, + }} {...form.getInputProps("password")} /> diff --git a/apps/client/src/features/user/components/change-password.tsx b/apps/client/src/features/user/components/change-password.tsx index 0925cdc48..9c0b4cb3d 100644 --- a/apps/client/src/features/user/components/change-password.tsx +++ b/apps/client/src/features/user/components/change-password.tsx @@ -95,6 +95,11 @@ function ChangePasswordForm({ onClose }: ChangePasswordFormProps) { variant="filled" mb="md" data-autofocus + visibilityToggleButtonProps={{ + "aria-label": t("Toggle password visibility"), + "aria-hidden": false, + tabIndex: 0, + }} {...form.getInputProps("oldPassword")} /> @@ -103,6 +108,11 @@ function ChangePasswordForm({ onClose }: ChangePasswordFormProps) { placeholder={t("Enter your new password")} variant="filled" mb="md" + visibilityToggleButtonProps={{ + "aria-label": t("Toggle password visibility"), + "aria-hidden": false, + tabIndex: 0, + }} {...form.getInputProps("newPassword")} /> diff --git a/apps/client/src/features/user/components/notification-pref.tsx b/apps/client/src/features/user/components/notification-pref.tsx index e8a983ede..cce519f91 100644 --- a/apps/client/src/features/user/components/notification-pref.tsx +++ b/apps/client/src/features/user/components/notification-pref.tsx @@ -3,7 +3,7 @@ import { updateUser } from "@/features/user/services/user-service.ts"; import { IUser, IUserSettings } from "@/features/user/types/user.types.ts"; import { Switch, Text, Title, Stack } from "@mantine/core"; import { useAtom } from "jotai"; -import React, { useState } from "react"; +import React, { useId, useState } from "react"; import { useTranslation } from "react-i18next"; import { ResponsiveSettingsRow, @@ -64,6 +64,8 @@ function NotificationToggle({ description: string; }) { const { t } = useTranslation(); + const switchId = useId(); + const descriptionId = useId(); const [user, setUser] = useAtom(userAtom); const [checked, setChecked] = useState( user.settings?.notifications?.[settingKey] !== false, @@ -83,14 +85,21 @@ function NotificationToggle({ return ( - {t(label)} - + + {t(label)} + + {t(description)} - + ); @@ -101,7 +110,7 @@ export default function NotificationPref() { return ( - {t("Email notifications")} + {t("Email notifications")} {notificationItems.map((item) => ( - + diff --git a/apps/client/src/features/workspace/components/members/components/workspace-invite-form.tsx b/apps/client/src/features/workspace/components/members/components/workspace-invite-form.tsx index aa9d3d90a..8deddc7d5 100644 --- a/apps/client/src/features/workspace/components/members/components/workspace-invite-form.tsx +++ b/apps/client/src/features/workspace/components/members/components/workspace-invite-form.tsx @@ -56,6 +56,12 @@ export function WorkspaceInviteForm({ onClose }: Props) { maxDropdownHeight={200} maxTags={50} onChange={setEmails} + data-autofocus + autoComplete="off" + data-1p-ignore + data-lpignore="true" + data-bwignore + data-form-type="other" />