Merge pull request #659 from buster-so/devin/BUS-1605-1754181219

feat: implement reports API endpoints for BUS-1605
This commit is contained in:
Nate Kelley 2025-08-02 21:49:24 -06:00 committed by GitHub
commit 729468d5cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 346 additions and 41 deletions

View File

@ -34,14 +34,18 @@
"@hono/zod-validator": "^0.7.2",
"@supabase/supabase-js": "catalog:",
"@trigger.dev/sdk": "catalog:",
"drizzle-orm": "catalog:",
"ai": "catalog:",
"drizzle-orm": "catalog:",
"hono": "catalog:",
"hono-pino": "^0.10.1",
"lodash-es": "^4.17.21",
"pino": "^9.7.0",
"pino-pretty": "^13.0.0",
"typescript": "5.8.3",
"tsup": "catalog:",
"typescript": "5.8.3",
"zod": "catalog:"
},
"devDependencies": {
"@types/lodash-es": "^4.17.12"
}
}

View File

@ -5,6 +5,7 @@ import chatsRoutes from './chats';
import dictionariesRoutes from './dictionaries';
import electricShapeRoutes from './electric-shape';
import organizationRoutes from './organization';
import reportsRoutes from './reports';
import securityRoutes from './security';
import slackRoutes from './slack';
import supportRoutes from './support';
@ -23,6 +24,7 @@ const app = new Hono()
.route('/organizations', organizationRoutes)
.route('/dictionaries', dictionariesRoutes)
.route('/title', titleRoutes)
.route('/temp', tempRoutes);
.route('/temp', tempRoutes)
.route('/reports', reportsRoutes);
export default app;

View File

@ -0,0 +1,70 @@
import type { User } from '@buster/database';
import type {
GetReportsListRequest,
GetReportsListResponse,
ReportListItem,
} from '@buster/server-shared/reports';
import { GetReportsListRequestSchema } from '@buster/server-shared/reports';
import { zValidator } from '@hono/zod-validator';
import { Hono } from 'hono';
async function getReportsListHandler(
request: GetReportsListRequest,
user: User
): Promise<GetReportsListResponse> {
const stubbedReports: ReportListItem[] = [
{
id: 'report-1',
name: 'Sales Analysis Q4',
file_name: 'sales_analysis_q4.md',
description: 'Quarterly sales performance analysis',
created_by: user.id,
updated_at: '2024-01-20T14:30:00Z',
},
{
id: 'report-2',
name: 'Customer Metrics Dashboard',
file_name: 'customer_metrics.md',
description: 'Key customer engagement metrics',
created_by: user.id,
updated_at: '2024-01-18T16:45:00Z',
},
{
id: 'report-3',
name: 'Marketing Campaign Results',
file_name: 'marketing_campaign_results.md',
description: 'Analysis of recent marketing campaigns',
created_by: user.id,
updated_at: '2024-01-12T11:15:00Z',
},
];
const { page, page_size } = request;
// Page is 1-based, so we need to subtract 1 for array indexing
const startIndex = (page - 1) * page_size;
const endIndex = startIndex + page_size;
const paginatedReports: ReportListItem[] = stubbedReports.slice(startIndex, endIndex);
const result: GetReportsListResponse = {
data: paginatedReports,
pagination: {
page,
page_size,
total: stubbedReports.length,
total_pages: Math.ceil(stubbedReports.length / page_size),
},
};
return result;
}
const app = new Hono().get('/', zValidator('query', GetReportsListRequestSchema), async (c) => {
const request = c.req.valid('query');
const user = c.get('busterUser');
const response = await getReportsListHandler(request, user);
return c.json(response);
});
export default app;

View File

@ -0,0 +1,55 @@
import type { User } from '@buster/database';
import type {
GetReportIndividualResponse,
ReportIndividualResponse,
} from '@buster/server-shared/reports';
import { zValidator } from '@hono/zod-validator';
import { Hono } from 'hono';
import { HTTPException } from 'hono/http-exception';
async function getReportHandler(
reportId: string,
user: User
): Promise<GetReportIndividualResponse> {
return {
id: reportId,
name: 'Sales Analysis Q4',
file_name: 'sales_analysis_q4.md',
description: 'Quarterly sales performance analysis',
created_by: user.id,
created_at: '2024-01-15T10:00:00Z',
updated_at: '2024-01-20T14:30:00Z',
deleted_at: null,
publicly_accessible: false,
content: [
{
type: 'h1',
children: [{ text: 'Sales Analysis Q4' }],
},
{
type: 'p',
children: [{ text: 'This report analyzes our Q4 sales performance.' }],
},
{
type: 'metric',
metricId: '123',
children: [{ text: '' }],
caption: [{ text: 'This is a metric' }],
},
],
};
}
const app = new Hono().get('/', async (c) => {
const reportId = c.req.param('id');
const user = c.get('busterUser');
if (!reportId) {
throw new HTTPException(404, { message: 'Report ID is required' });
}
const response: GetReportIndividualResponse = await getReportHandler(reportId, user);
return c.json(response);
});
export default app;

View File

@ -0,0 +1,61 @@
import type { User } from '@buster/database';
import type { UpdateReportRequest, UpdateReportResponse } from '@buster/server-shared/reports';
import { UpdateReportRequestSchema } from '@buster/server-shared/reports';
import { zValidator } from '@hono/zod-validator';
import { Hono } from 'hono';
import { HTTPException } from 'hono/http-exception';
async function updateReportHandler(
reportId: string,
request: UpdateReportRequest,
user: User
): Promise<UpdateReportResponse> {
const existingReport: UpdateReportResponse = {
id: reportId,
name: 'Sales Analysis Q4',
file_name: 'sales_analysis_q4.md',
description: 'Quarterly sales performance analysis',
created_by: user.id,
created_at: '2024-01-15T10:00:00Z',
updated_at: '2024-01-20T14:30:00Z',
deleted_at: null,
publicly_accessible: false,
content: [
{
type: 'h1' as const,
children: [{ text: 'Sales Analysis Q4' }],
},
{
type: 'p' as const,
children: [{ text: 'This report analyzes our Q4 sales performance.' }],
},
],
};
if (!reportId || reportId === 'invalid') {
throw new HTTPException(404, { message: 'Report not found' });
}
const updatedReport: UpdateReportResponse = {
...existingReport,
...(request as Partial<UpdateReportResponse>),
updated_at: new Date().toISOString(),
};
return updatedReport;
}
const app = new Hono().put('/', zValidator('json', UpdateReportRequestSchema), async (c) => {
const reportId = c.req.param('id');
const request = c.req.valid('json');
const user = c.get('busterUser');
if (!reportId) {
throw new HTTPException(404, { message: 'Report ID is required' });
}
const response = await updateReportHandler(reportId, request, user);
return c.json(response);
});
export default app;

View File

@ -0,0 +1,8 @@
import { Hono } from 'hono';
import { requireAuth } from '../../../../middleware/auth';
import GET from './GET';
import PUT from './PUT';
const app = new Hono().route('/', GET).route('/', PUT);
export default app;

View File

@ -0,0 +1,8 @@
import { Hono } from 'hono';
import { requireAuth } from '../../../middleware/auth';
import GET from './GET';
import individualReport from './[id]';
const app = new Hono().use('*', requireAuth).route('/', GET).route('/:id', individualReport);
export default app;

View File

@ -287,7 +287,7 @@ export const SAMPLE_REPORT_ELEMENTS = [
{
type: 'metric',
metricId: '123',
children: [{ text: '100' }],
children: [{ text: '' }],
caption: [{ text: 'This is a metric' }],
},
] satisfies ReportElement[];

View File

@ -1 +1,5 @@
export * from './report-elements';
export * from './reports.types';
export * from './requests';
export * from './responses';
export * from './reports.types';

View File

@ -50,6 +50,10 @@ export const SimpleTextSchema = z
})
.merge(AttributesSchema);
export const VoidTextSchema = z.object({
text: z.literal(''),
});
/**
* Inline Elements
* ---------------
@ -74,7 +78,7 @@ export const AnchorSchema = z.object({
const DateSchema = z.object({
type: z.literal('date'),
date: z.string(),
children: z.array(TextSchema),
children: z.array(VoidTextSchema),
id: z.string().optional(),
});
@ -152,7 +156,7 @@ export const ImageElementSchema = z
alt: z.string().optional(),
width: z.union([z.number(), z.string().regex(/^(?:\d+px|\d+%)$/)]).optional(),
height: z.number().optional(),
children: z.array(TextSchema).default([]),
children: z.array(VoidTextSchema).default([]),
caption: z.array(z.union([TextSchema, ParagraphElementSchema])).default([]),
id: z.string().optional(),
})
@ -163,7 +167,7 @@ export const EmojiElementSchema = z.object({
type: z.literal('emoji'),
emoji: z.string().optional(),
code: z.string().optional(),
children: z.array(TextSchema).default([]),
children: z.array(VoidTextSchema).default([]),
id: z.string().optional(),
});
@ -171,7 +175,7 @@ export const EmojiElementSchema = z.object({
export const AudioElementSchema = z.object({
type: z.literal('audio'),
url: z.string(),
children: z.array(TextSchema).default([]),
children: z.array(VoidTextSchema).default([]),
id: z.string().optional(),
});
@ -181,14 +185,14 @@ export const FileElementSchema = z.object({
url: z.string(),
name: z.string(),
isUpload: z.boolean().optional(),
children: z.array(TextSchema),
children: z.array(VoidTextSchema),
id: z.string().optional(),
});
// Table of Contents element
export const TocElementSchema = z.object({
type: z.literal('toc'),
children: z.array(TextSchema).default([]),
children: z.array(VoidTextSchema).default([]),
id: z.string().optional(),
});
@ -345,10 +349,21 @@ export const ListItemElementSchema = z.object({
children: z.array(TextSchema).default([]),
});
// Equation element
export const EquationElementSchema = z.object({
type: z.literal('equation'),
id: z.string().optional(),
texExpression: z.string(),
children: z.array(VoidTextSchema).default([]),
});
// CUSTOM ELEMENTS
export const MetricElementSchema = z.object({
type: z.literal('metric'),
metricId: z.string(),
children: z.array(SimpleTextSchema).default([]),
children: z.array(VoidTextSchema).default([]),
caption: z.array(z.union([TextSchema, ParagraphElementSchema])).default([]),
});
@ -357,17 +372,10 @@ export const MediaEmbedElementSchema = z.object({
id: z.string().optional(),
url: z.string(),
width: z.union([z.number(), z.string().regex(/^(?:\d+px|\d+%)$/)]).optional(),
children: z.array(SimpleTextSchema).default([]),
children: z.array(VoidTextSchema).default([]),
caption: z.array(z.union([TextSchema, ParagraphElementSchema])).default([]),
});
export const EquationElementSchema = z.object({
type: z.literal('equation'),
id: z.string().optional(),
texExpression: z.string(),
children: z.array(SimpleTextSchema).default([]),
});
/**
* Composite Schemas
* -----------------
@ -404,11 +412,6 @@ export const ReportElementSchema = z.discriminatedUnion('type', [
// Array of report elements for complete documents
export const ReportElementsSchema = z.array(ReportElementSchema);
/**
* Exported TypeScript Types
* -------------------------
* Inferred types from Zod schemas for type-safe usage.
*/
export type TextElement = z.infer<typeof TextSchema>;
export type SimpleTextElement = z.infer<typeof SimpleTextSchema>;
export type MentionElement = z.infer<typeof MentionSchema>;

View File

@ -0,0 +1,39 @@
import { z } from 'zod';
import type { ReportElement, ReportElements } from './report-elements';
import { ReportElementSchema } from './report-elements';
export const ReportListItemSchema = z.object({
id: z.string(),
name: z.string(),
file_name: z.string(),
description: z.string(),
created_by: z.string(),
updated_at: z.string(),
});
export const ReportIndividualResponseSchema: z.ZodType<{
id: string;
name: string;
file_name: string;
description: string;
created_by: string;
created_at: string;
updated_at: string;
deleted_at: string | null;
publicly_accessible: boolean;
content: ReportElement[];
}> = z.object({
id: z.string(),
name: z.string(),
file_name: z.string(),
description: z.string(),
created_by: z.string(),
created_at: z.string(),
updated_at: z.string(),
deleted_at: z.string().nullable(),
publicly_accessible: z.boolean(),
content: z.array(ReportElementSchema) as z.ZodType<ReportElements>,
});
export type ReportListItem = z.infer<typeof ReportListItemSchema>;
export type ReportIndividualResponse = z.infer<typeof ReportIndividualResponseSchema>;

View File

@ -0,0 +1,21 @@
import { z } from 'zod';
import { PaginatedRequestSchema } from '../type-utilities/pagination';
import type { ReportElement, ReportElements } from './report-elements';
import { ReportElementSchema } from './report-elements';
export const GetReportsListRequestSchema = PaginatedRequestSchema;
// Define UpdateReportRequestSchema with explicit type annotation
export const UpdateReportRequestSchema = z
.object({
name: z.string().optional(),
description: z.string().optional(),
publicly_accessible: z.boolean().optional(),
content: z.lazy(() => z.array(ReportElementSchema)).optional() as z.ZodOptional<
z.ZodType<ReportElements>
>,
})
.partial();
export type UpdateReportRequest = z.infer<typeof UpdateReportRequestSchema>;
export type GetReportsListRequest = z.infer<typeof GetReportsListRequestSchema>;

View File

@ -0,0 +1,10 @@
import type { z } from 'zod';
import { PaginatedResponseSchema } from '../type-utilities/pagination';
import { ReportIndividualResponseSchema, ReportListItemSchema } from './reports.types';
export const GetReportsListResponseSchema = PaginatedResponseSchema(ReportListItemSchema);
export const UpdateReportResponseSchema = ReportIndividualResponseSchema;
export type GetReportsListResponse = z.infer<typeof GetReportsListResponseSchema>;
export type UpdateReportResponse = z.infer<typeof UpdateReportResponseSchema>;
export type GetReportIndividualResponse = z.infer<typeof ReportIndividualResponseSchema>;

View File

@ -16,3 +16,8 @@ export const PaginatedResponseSchema = <T>(schema: z.ZodType<T>) =>
});
export type PaginatedResponse<T> = z.infer<ReturnType<typeof PaginatedResponseSchema<T>>>;
export const PaginatedRequestSchema = z.object({
page: z.coerce.number().min(1).default(1),
page_size: z.coerce.number().min(1).max(5000).default(250),
});

View File

@ -175,6 +175,9 @@ importers:
hono-pino:
specifier: ^0.10.1
version: 0.10.1(hono@4.8.4)(pino@9.7.0)
lodash-es:
specifier: ^4.17.21
version: 4.17.21
pino:
specifier: ^9.7.0
version: 9.7.0
@ -190,6 +193,10 @@ importers:
zod:
specifier: 'catalog:'
version: 3.25.1
devDependencies:
'@types/lodash-es':
specifier: ^4.17.12
version: 4.17.12
apps/trigger:
dependencies:
@ -298,10 +305,10 @@ importers:
version: 49.2.4(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)
'@platejs/autoformat':
specifier: 'catalog:'
version: 49.0.0(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 49.0.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@platejs/basic-nodes':
specifier: 'catalog:'
version: 49.0.0(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 49.0.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@platejs/basic-styles':
specifier: ^49.0.0
version: 49.0.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -352,7 +359,7 @@ importers:
version: 49.2.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@platejs/markdown':
specifier: 'catalog:'
version: 49.2.1(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)
version: 49.2.1(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)
'@platejs/math':
specifier: ^49.0.0
version: 49.0.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@ -1038,13 +1045,13 @@ importers:
version: link:../vitest-config
'@platejs/autoformat':
specifier: 'catalog:'
version: 49.0.0(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 49.0.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@platejs/basic-nodes':
specifier: 'catalog:'
version: 49.0.0(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
version: 49.0.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@platejs/markdown':
specifier: 'catalog:'
version: 49.2.1(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)
version: 49.2.1(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)
platejs:
specifier: 'catalog:'
version: 49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1))
@ -5771,6 +5778,9 @@ packages:
'@types/katex@0.16.7':
resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
'@types/lodash-es@4.17.12':
resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
'@types/lodash@4.17.20':
resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==}
@ -6773,6 +6783,7 @@ packages:
bun@1.2.18:
resolution: {integrity: sha512-OR+EpNckoJN4tHMVZPaTPxDj2RgpJgJwLruTIFYbO3bQMguLd0YrmkWKYqsiihcLgm2ehIjF/H1RLfZiRa7+qQ==}
cpu: [arm64, x64, aarch64]
os: [darwin, linux, win32]
hasBin: true
@ -16479,7 +16490,7 @@ snapshots:
'@platejs/ai@49.2.4(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)':
dependencies:
'@platejs/markdown': 49.2.1(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)
'@platejs/markdown': 49.2.1(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)
'@platejs/selection': 49.2.4(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
lodash: 4.17.21
platejs: 49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1))
@ -16489,14 +16500,14 @@ snapshots:
- supports-color
- typescript
'@platejs/autoformat@49.0.0(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@platejs/autoformat@49.0.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
lodash: 4.17.21
platejs: 49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1))
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@platejs/basic-nodes@49.0.0(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
'@platejs/basic-nodes@49.0.0(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
platejs: 49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1))
react: 18.3.1
@ -16552,7 +16563,7 @@ snapshots:
html-entities: 2.6.0
is-hotkey: 0.2.0
jotai: 2.8.4(@types/react@18.3.23)(react@18.3.1)
jotai-optics: 0.4.0(jotai@2.8.4(react@18.3.1))(optics-ts@2.4.1)
jotai-optics: 0.4.0(jotai@2.8.4(@types/react@18.3.23)(react@18.3.1))(optics-ts@2.4.1)
jotai-x: 2.3.3(@types/react@18.3.23)(jotai@2.8.4(@types/react@18.3.23)(react@18.3.1))(react@18.3.1)
lodash: 4.17.21
nanoid: 5.1.5
@ -16563,7 +16574,7 @@ snapshots:
slate-react: 0.117.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)
use-deep-compare: 1.3.0(react@18.3.1)
zustand: 5.0.7(@types/react@18.3.23)(immer@10.1.1)(react@18.3.1)(use-sync-external-store@1.5.0(react@18.3.1))
zustand-x: 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(zustand@5.0.7(immer@10.1.1)(react@18.3.1)(use-sync-external-store@1.5.0(react@18.3.1)))
zustand-x: 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(zustand@5.0.7(@types/react@18.3.23)(immer@10.1.1)(react@18.3.1)(use-sync-external-store@1.5.0(react@18.3.1)))
transitivePeerDependencies:
- '@types/react'
- immer
@ -16654,7 +16665,7 @@ snapshots:
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
'@platejs/markdown@49.2.1(platejs@49.2.4(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)':
'@platejs/markdown@49.2.1(platejs@49.2.4(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.8.3)':
dependencies:
marked: 15.0.12
mdast-util-math: 3.0.0
@ -18761,6 +18772,10 @@ snapshots:
'@types/katex@0.16.7': {}
'@types/lodash-es@4.17.12':
dependencies:
'@types/lodash': 4.17.20
'@types/lodash@4.17.20': {}
'@types/mdast@4.0.4':
@ -19207,14 +19222,14 @@ snapshots:
msw: 2.10.4(@types/node@20.19.4)(typescript@5.8.3)
vite: 6.3.5(@types/node@20.19.4)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
'@vitest/mocker@3.2.4(msw@2.10.4(@types/node@24.0.10)(typescript@5.8.3))(vite@6.3.5(@types/node@20.19.4)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
'@vitest/mocker@3.2.4(msw@2.10.4(@types/node@24.0.10)(typescript@5.8.3))(vite@6.3.5(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
msw: 2.10.4(@types/node@24.0.10)(typescript@5.8.3)
vite: 6.3.5(@types/node@20.19.4)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
vite: 6.3.5(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
'@vitest/pretty-format@2.0.5':
dependencies:
@ -22519,7 +22534,7 @@ snapshots:
jose@5.10.0: {}
jotai-optics@0.4.0(jotai@2.8.4(react@18.3.1))(optics-ts@2.4.1):
jotai-optics@0.4.0(jotai@2.8.4(@types/react@18.3.23)(react@18.3.1))(optics-ts@2.4.1):
dependencies:
jotai: 2.8.4(@types/react@18.3.23)(react@18.3.1)
optics-ts: 2.4.1
@ -26543,7 +26558,7 @@ snapshots:
dependencies:
'@types/chai': 5.2.2
'@vitest/expect': 3.2.4
'@vitest/mocker': 3.2.4(msw@2.10.4(@types/node@24.0.10)(typescript@5.8.3))(vite@6.3.5(@types/node@20.19.4)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
'@vitest/mocker': 3.2.4(msw@2.10.4(@types/node@24.0.10)(typescript@5.8.3))(vite@6.3.5(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))
'@vitest/pretty-format': 3.2.4
'@vitest/runner': 3.2.4
'@vitest/snapshot': 3.2.4
@ -26950,7 +26965,7 @@ snapshots:
zod@3.25.1: {}
zustand-x@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(zustand@5.0.7(immer@10.1.1)(react@18.3.1)(use-sync-external-store@1.5.0(react@18.3.1))):
zustand-x@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.23.2)(zustand@5.0.7(@types/react@18.3.23)(immer@10.1.1)(react@18.3.1)(use-sync-external-store@1.5.0(react@18.3.1))):
dependencies:
immer: 10.1.1
lodash.mapvalues: 4.6.0