feat: entry editor at /content/:key/new and /content/:key/:id

This commit is contained in:
Florian Sylvain committed 2026-10-21 00:12:34 +02:00
1 parent 91d916fb74
commit fba20f83c5
94 files changed
+7116 -423

No files matched your search

+30 -2
View File
@@ -134,7 +134,15 @@ function defaultType(key: string) {
return found
}
export interface EntryWrite {
method: string
url: string
body: Record<string, unknown>
}
export interface SchemaMount {
entry?: (key: string, id: number) => unknown
writeEntry?: (write: EntryWrite) => unknown
role?: string
create?: (body: PostedRequest['body']) => unknown
update?: (body: PostedRequest['body'], key: string) => unknown
@@ -144,6 +152,7 @@ export interface SchemaMount {
content?: Responder
builtin?: Responder
verified?: boolean
status?: 'checking' | 'ready'
actions?: string[]
type?: (key: string) => unknown
list?: (key: string, query: URLSearchParams) => unknown
@@ -156,6 +165,8 @@ export const calls: string[] = []
export const posts: PostedRequest[] = []
export const puts: PostedRequest[] = []
export const deletes: string[] = []
export const entryWrites: EntryWrite[] = []
const ENTRY_URL = /^\/v1\/content-type\/[^/?]+\/entry(\/\d+)?$/
export function updatedType(key: string, body: Record<string, unknown>) {
const base = customTypes.find((type) => type.key === key)!
@@ -167,6 +178,7 @@ export async function mountAt(path: string, options: SchemaMount = {}, shellOnly
posts.length = 0
puts.length = 0
deletes.length = 0
entryWrites.length = 0
localStorage.clear()
options.before?.()
setViewportWidth(options.width ?? DESKTOP_WIDTH)
@@ -187,8 +199,17 @@ export async function mountAt(path: string, options: SchemaMount = {}, shellOnly
displayName: 'Marta Alves',
role: (options.role ?? 'owner') as never,
}
session.status = 'ready'
session.status = options.status ?? 'ready'
const request = vi.fn(async (url: string, init?: RequestInit) => {
if (init?.method && ENTRY_URL.test(url)) {
const write = {
method: init.method,
url,
body: init.body ? (JSON.parse(String(init.body)) as Record<string, unknown>) : {},
}
entryWrites.push(write)
return options.writeEntry?.(write)
}
if (init?.method === 'DELETE') {
deletes.push(url)
return (options.remove ?? (() => undefined))(url.split('/').pop()!)
@@ -223,6 +244,10 @@ export async function mountAt(path: string, options: SchemaMount = {}, shellOnly
if (looked) {
return (options.lookup ?? (() => []))(looked[1]!.split(',').map(Number))
}
const single = url.match(/^\/v1\/content-type\/([^/?]+)\/entry\/(\d+)$/)
if (single) {
return options.entry?.(single[1]!, Number(single[2]))
}
const detailed = url.match(/^\/v1\/content-type\/([^/?]+)$/)
if (detailed) {
return (options.type ?? defaultType)(detailed[1]!)
@@ -233,7 +258,10 @@ export async function mountAt(path: string, options: SchemaMount = {}, shellOnly
return undefined
})
vi.mocked(useApi).mockReturnValue({
getMe: vi.fn().mockResolvedValue({ verified: true, username: 'marta' }),
getMe:
options.status === 'checking'
? vi.fn(() => new Promise(() => undefined))
: vi.fn().mockResolvedValue({ verified: true, username: 'marta' }),
request,
} as unknown as ReturnType<typeof useApi>)
await router.push(path)