34 lines
1.2 KiB
TypeScript
34 lines
1.2 KiB
TypeScript
|
|
import { z } from 'zod';
|
||
|
|
import { CursorSchema } from './primitives.js';
|
||
|
|
|
||
|
|
export const FileKindSchema = z.enum(['file', 'dir']);
|
||
|
|
export type FileKind = z.infer<typeof FileKindSchema>;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Directory entry shape. App-specific extension via `metadata` — keep it
|
||
|
|
* lean; large blobs (thumbnails) belong in `getThumbnail`, not here.
|
||
|
|
*/
|
||
|
|
export const FileEntrySchema = z.object({
|
||
|
|
/** Base name only — no path separators. */
|
||
|
|
name: z.string().min(1).max(512).refine((s) => !s.includes('/') && !s.includes('\\'), {
|
||
|
|
message: 'name must not contain path separators',
|
||
|
|
}),
|
||
|
|
kind: FileKindSchema,
|
||
|
|
/** Plaintext byte size; 0 for directories. */
|
||
|
|
size: z.number().int().nonnegative(),
|
||
|
|
/** Last-modified time, unix milliseconds. */
|
||
|
|
mtime: z.number().int(),
|
||
|
|
/** RFC 6838 media type if known. */
|
||
|
|
contentType: z.string().max(255).optional(),
|
||
|
|
/** App-specific extension fields. Default empty. */
|
||
|
|
metadata: z.record(z.string(), z.unknown()).default({}),
|
||
|
|
});
|
||
|
|
export type FileEntry = z.infer<typeof FileEntrySchema>;
|
||
|
|
|
||
|
|
export const ListPageSchema = z.object({
|
||
|
|
entries: z.array(FileEntrySchema),
|
||
|
|
nextCursor: CursorSchema.optional(),
|
||
|
|
hasMore: z.boolean(),
|
||
|
|
});
|
||
|
|
export type ListPage = z.infer<typeof ListPageSchema>;
|