@withwiz/gallery 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +20 -1
- package/README.md +20 -1
- package/dist/chunk-IEXSUEDO.mjs +78 -0
- package/dist/chunk-IEXSUEDO.mjs.map +1 -0
- package/dist/chunk-IYQOJJBC.js +78 -0
- package/dist/chunk-IYQOJJBC.js.map +1 -0
- package/dist/server/index.d.mts +4 -0
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.js +67 -8
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +62 -3
- package/dist/server/index.mjs.map +1 -1
- package/dist/types/index.d.mts +15 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/validators/index.d.mts +17 -3
- package/dist/validators/index.d.ts +17 -3
- package/dist/validators/index.js +8 -2
- package/dist/validators/index.js.map +1 -1
- package/dist/validators/index.mjs +7 -1
- package/package.json +9 -3
- package/dist/chunk-ILSZPLME.js +0 -47
- package/dist/chunk-ILSZPLME.js.map +0 -1
- package/dist/chunk-YUMB3GBN.mjs +0 -47
- package/dist/chunk-YUMB3GBN.mjs.map +0 -1
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-gallery/dist/server/index.js","../../src/services/helpers.ts","../../src/services/category-service.ts","../../src/services/index.ts","../../src/server/route-handlers.ts","../../src/utils/api-helpers.ts","../../src/server/loaders.ts"],"names":["NextResponse"],"mappings":"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","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-gallery/dist/server/index.js","sourcesContent":[null,"import type { PaginatedResult } from \"../types/pagination\";\n\n/**\n * pagination math 를 일관되게 처리. ballet 의 `buildPaginatedResult` 와 동일 시맨틱.\n *\n * - total === 0 일 때 totalPages = 0 (clamp 안 함; UI 에서 \"결과 없음\" 로 처리)\n * - page > totalPages 여도 결과 자체는 caller 의 query 가 결정 — meta 만 계산\n */\nexport function buildPaginatedResult<T>(\n items: T[],\n page: number,\n limit: number,\n total: number,\n): PaginatedResult<T> {\n const totalPages = total === 0 ? 0 : Math.ceil(total / limit);\n return {\n items,\n meta: {\n page,\n limit,\n total,\n totalPages,\n hasNext: page < totalPages,\n hasPrev: page > 1,\n },\n };\n}\n","import type {\n GalleryConfig,\n GalleryCategoryItem,\n CreateCategoryInput,\n UpdateCategoryInput,\n} from \"../types\";\nimport { CategoryInUseError } from \"../errors\";\n\n/**\n * spec §9-2 의 categoryService.\n *\n * 호스트 독립성을 위해 Prisma delegate 는 `config.prisma[modelName]` 패턴으로 접근한다\n * (modelName 기본값 = \"galleryCategory\", gallery 본체 modelName 기본값 = \"gallery\").\n *\n * remove() 는 `onDelete: Restrict` 보강 — 사전 gallery.count() 후 throw.\n * admin UX 가 친화적 에러 메시지를 표시하도록 명시적 throw 를 사용.\n */\nexport function createCategoryService(config: GalleryConfig) {\n const categoryDelegate = () =>\n config.prisma[config.categoryModelName ?? \"galleryCategory\"];\n const galleryDelegate = () => config.prisma[config.modelName ?? \"gallery\"];\n\n async function list(opts?: { isActive?: boolean }): Promise<GalleryCategoryItem[]> {\n const where =\n opts?.isActive !== undefined ? { isActive: opts.isActive } : undefined;\n const rows = await categoryDelegate().findMany({\n ...(where ? { where } : {}),\n orderBy: [{ sortOrder: \"asc\" }, { createdAt: \"asc\" }],\n });\n return rows as GalleryCategoryItem[];\n }\n\n async function getBySlug(slug: string): Promise<GalleryCategoryItem | null> {\n const row = await categoryDelegate().findUnique({ where: { slug } });\n return (row as GalleryCategoryItem | null) ?? null;\n }\n\n async function getById(id: string): Promise<GalleryCategoryItem | null> {\n const row = await categoryDelegate().findUnique({ where: { id } });\n return (row as GalleryCategoryItem | null) ?? null;\n }\n\n async function create(data: CreateCategoryInput): Promise<GalleryCategoryItem> {\n const row = await categoryDelegate().create({ data });\n return row as GalleryCategoryItem;\n }\n\n async function update(\n id: string,\n data: UpdateCategoryInput,\n ): Promise<GalleryCategoryItem> {\n const row = await categoryDelegate().update({ where: { id }, data });\n return row as GalleryCategoryItem;\n }\n\n /**\n * 사용 중 카테고리 (galleries 가 참조) 는 삭제 차단.\n * DB 의 `onDelete: Restrict` 가 최종 방어선이지만, 친화적 에러를 위해 사전 count.\n */\n async function remove(id: string): Promise<void> {\n const inUse = await galleryDelegate().count({ where: { categoryId: id } });\n if (inUse > 0) {\n throw new CategoryInUseError(id, inUse);\n }\n await categoryDelegate().delete({ where: { id } });\n }\n\n /**\n * ids 배열 순서대로 sortOrder = 0..N-1 로 갱신.\n * 단일 mutation 묶음 — $transaction 사용 (배열 형태).\n */\n async function reorder(ids: string[]): Promise<void> {\n const ops = ids.map((id, idx) =>\n categoryDelegate().update({ where: { id }, data: { sortOrder: idx } }),\n );\n await config.prisma.$transaction(ops);\n }\n\n return { list, getBySlug, getById, create, update, remove, reorder };\n}\n\nexport type CategoryService = ReturnType<typeof createCategoryService>;\n","import type {\n GalleryConfig,\n GalleryDetail,\n GalleryListItem,\n CreateGalleryInput,\n UpdateGalleryInput,\n PaginatedResult,\n} from \"../types\";\nimport { GalleryNotFoundError } from \"../errors\";\nimport { buildPaginatedResult } from \"./helpers\";\n\nexport { buildPaginatedResult } from \"./helpers\";\nexport { createCategoryService } from \"./category-service\";\nexport type { CategoryService } from \"./category-service\";\n\ntype SortKey = \"sortOrder\" | \"createdAt\" | \"updatedAt\" | \"caption\";\n\n/**\n * spec §9-2 의 createGalleryService.\n *\n * 핵심 규칙:\n * - Prisma delegate 는 `config.prisma[config.modelName ?? \"gallery\"]` 패턴.\n * - `include: { category: true }` 만 사용. **author include 금지** (Gallery 모델에 author 관계 없음, §3 호스트 독립 원칙).\n * - 삭제 시 `config.storage` 가 isEnabled() true 면 collectKeys → deleteKeys.\n * - `revalidate` 는 service 에서 호출하지 않음 (route handler 책임).\n */\nexport function createGalleryService(config: GalleryConfig) {\n const galleryDelegate = () => config.prisma[config.modelName ?? \"gallery\"];\n const baseInclude = { category: true } as const;\n\n function orderByFor(sortBy: SortKey) {\n switch (sortBy) {\n case \"sortOrder\":\n return [{ sortOrder: \"asc\" as const }, { createdAt: \"desc\" as const }];\n case \"caption\":\n return { caption: \"asc\" as const };\n case \"createdAt\":\n case \"updatedAt\":\n return { [sortBy]: \"desc\" as const };\n }\n }\n\n // ── Public-facing read methods ─────────────────────\n\n async function listFeatured(limit?: number): Promise<GalleryListItem[]> {\n const rows = await galleryDelegate().findMany({\n where: { published: true, featured: true },\n include: baseInclude,\n orderBy: [{ sortOrder: \"asc\" }, { createdAt: \"desc\" }],\n ...(limit ? { take: limit } : {}),\n });\n return rows as GalleryListItem[];\n }\n\n async function listPublished(limit?: number): Promise<GalleryListItem[]> {\n const rows = await galleryDelegate().findMany({\n where: { published: true },\n include: baseInclude,\n orderBy: [{ sortOrder: \"asc\" }, { createdAt: \"desc\" }],\n ...(limit ? { take: limit } : {}),\n });\n return rows as GalleryListItem[];\n }\n\n async function listPublishedByCategory(\n categorySlug: string,\n limit?: number,\n ): Promise<GalleryListItem[]> {\n const rows = await galleryDelegate().findMany({\n where: { published: true, category: { slug: categorySlug } },\n include: baseInclude,\n orderBy: [{ sortOrder: \"asc\" }, { createdAt: \"desc\" }],\n ...(limit ? { take: limit } : {}),\n });\n return rows as GalleryListItem[];\n }\n\n // ── Admin list / detail ────────────────────────────\n\n async function listAll(opts: {\n page?: number;\n limit?: number;\n categoryId?: string;\n published?: boolean;\n search?: string;\n sortBy?: SortKey;\n }): Promise<PaginatedResult<GalleryListItem>> {\n const page = opts.page ?? 1;\n const limit = opts.limit ?? 20;\n const sortBy = opts.sortBy ?? \"sortOrder\";\n const skip = (page - 1) * limit;\n\n const where: Record<string, unknown> = {};\n if (opts.categoryId) where.categoryId = opts.categoryId;\n if (opts.published !== undefined) where.published = opts.published;\n if (opts.search) where.caption = { contains: opts.search, mode: \"insensitive\" };\n\n const [items, total] = await Promise.all([\n galleryDelegate().findMany({\n where,\n include: baseInclude,\n orderBy: orderByFor(sortBy),\n skip,\n take: limit,\n }),\n galleryDelegate().count({ where }),\n ]);\n\n return buildPaginatedResult(items as GalleryListItem[], page, limit, total);\n }\n\n async function getById(id: string): Promise<GalleryDetail | null> {\n const row = await galleryDelegate().findUnique({\n where: { id },\n include: baseInclude,\n });\n return (row as GalleryDetail | null) ?? null;\n }\n\n // ── Mutations ──────────────────────────────────────\n\n async function create(\n data: CreateGalleryInput,\n authorId: string,\n ): Promise<GalleryDetail> {\n const row = await galleryDelegate().create({\n data: {\n imageUrl: data.imageUrl,\n imageKey: data.imageKey ?? null,\n caption: data.caption ?? null,\n categoryId: data.categoryId,\n sortOrder: data.sortOrder ?? 0,\n featured: data.featured ?? false,\n published: data.published ?? false,\n authorId,\n },\n include: baseInclude,\n });\n return row as GalleryDetail;\n }\n\n async function createMany(\n items: CreateGalleryInput[],\n authorId: string,\n ): Promise<{ count: number }> {\n const result = await galleryDelegate().createMany({\n data: items.map((it) => ({\n imageUrl: it.imageUrl,\n imageKey: it.imageKey ?? null,\n caption: it.caption ?? null,\n categoryId: it.categoryId,\n sortOrder: it.sortOrder ?? 0,\n featured: it.featured ?? false,\n published: it.published ?? false,\n authorId,\n })),\n });\n return { count: result.count };\n }\n\n async function update(\n id: string,\n data: UpdateGalleryInput,\n ): Promise<GalleryDetail> {\n const patch: Record<string, unknown> = {};\n if (data.imageUrl !== undefined) patch.imageUrl = data.imageUrl;\n if (data.imageKey !== undefined) patch.imageKey = data.imageKey ?? null;\n if (data.caption !== undefined) patch.caption = data.caption ?? null;\n if (data.categoryId !== undefined) patch.categoryId = data.categoryId;\n if (data.sortOrder !== undefined) patch.sortOrder = data.sortOrder;\n if (data.featured !== undefined) patch.featured = data.featured;\n if (data.published !== undefined) patch.published = data.published;\n\n const row = await galleryDelegate().update({\n where: { id },\n data: patch,\n include: baseInclude,\n });\n return row as GalleryDetail;\n }\n\n async function remove(id: string): Promise<void> {\n const storageEnabled = config.storage?.isEnabled?.() === true;\n let imageKey: string | null = null;\n if (storageEnabled) {\n const row = (await galleryDelegate().findUnique({\n where: { id },\n select: { imageKey: true },\n })) as { imageKey: string | null } | null;\n imageKey = row?.imageKey ?? null;\n }\n await galleryDelegate().delete({ where: { id } });\n if (storageEnabled && imageKey && config.storage) {\n const keys = config.storage.collectKeys(imageKey);\n if (keys.length > 0) await config.storage.deleteKeys(keys);\n }\n }\n\n async function removeMany(ids: string[]): Promise<{ count: number }> {\n const storageEnabled = config.storage?.isEnabled?.() === true;\n let imageKeys: string[] = [];\n if (storageEnabled) {\n const rows = (await galleryDelegate().findMany({\n where: { id: { in: ids } },\n select: { imageKey: true },\n })) as Array<{ imageKey: string | null }>;\n imageKeys = rows\n .map((r) => r.imageKey)\n .filter((k): k is string => typeof k === \"string\" && k.length > 0);\n }\n const result = await galleryDelegate().deleteMany({ where: { id: { in: ids } } });\n if (storageEnabled && imageKeys.length > 0 && config.storage) {\n const allKeys = imageKeys.flatMap((k) => config.storage!.collectKeys(k));\n const uniqueKeys = [...new Set(allKeys)];\n if (uniqueKeys.length > 0) await config.storage.deleteKeys(uniqueKeys);\n }\n return { count: result.count };\n }\n\n async function bulkUpdatePublished(\n ids: string[],\n published: boolean,\n ): Promise<{ count: number }> {\n const result = await galleryDelegate().updateMany({\n where: { id: { in: ids } },\n data: { published, updatedAt: new Date() },\n });\n return { count: result.count };\n }\n\n async function bulkUpdateFeatured(\n ids: string[],\n featured: boolean,\n ): Promise<{ count: number }> {\n const result = await galleryDelegate().updateMany({\n where: { id: { in: ids } },\n data: { featured, updatedAt: new Date() },\n });\n return { count: result.count };\n }\n\n async function togglePublish(id: string): Promise<GalleryDetail> {\n const current = (await galleryDelegate().findUnique({\n where: { id },\n select: { published: true },\n })) as { published: boolean } | null;\n if (!current) {\n throw new GalleryNotFoundError(id);\n }\n const row = await galleryDelegate().update({\n where: { id },\n data: { published: !current.published },\n include: baseInclude,\n });\n return row as GalleryDetail;\n }\n\n async function count(opts?: { published?: boolean }): Promise<number> {\n const where = opts?.published !== undefined ? { published: opts.published } : undefined;\n const n = await galleryDelegate().count(where ? { where } : {});\n return n as number;\n }\n\n async function listRecent(limit: number): Promise<GalleryListItem[]> {\n const rows = await galleryDelegate().findMany({\n include: baseInclude,\n orderBy: { createdAt: \"desc\" },\n take: limit,\n });\n return rows as GalleryListItem[];\n }\n\n return {\n listFeatured,\n listPublished,\n listPublishedByCategory,\n listAll,\n getById,\n create,\n createMany,\n update,\n remove,\n removeMany,\n bulkUpdatePublished,\n bulkUpdateFeatured,\n togglePublish,\n count,\n listRecent,\n };\n}\n\nexport type GalleryService = ReturnType<typeof createGalleryService>;\n","/**\n * Route handler factory — spec §9-3.\n *\n * `createGalleryRoutes(config)` 가 host 의 `apiWrapper` 로 감싼 9 개 라우트를 반환한다.\n * host 는 각 라우트 파일에서 `export const { GET, POST } = galleryRoutes.collection` 식으로 사용.\n *\n * 설계 원칙:\n * - 모든 mutation 종료 직전 `config.revalidate?.(path)` 를 `config.revalidatePaths` 각 path 에 대해 호출.\n * - `config.permissions?.canEdit/canDelete` 가 함수면 호출 → false 시 403 반환.\n * 미설정이면 admin 전원 모든 권한 (spec §16 v0.1 정책).\n * - `ctx.params?.id` 는 host 미들웨어가 채워준다고 가정 (spec §6-1).\n * - 카테고리 `remove` 의 in-use 에러는 service throw → handler 가 잡아 409 반환.\n */\nimport { NextResponse } from \"next/server\";\nimport type {\n ApiContext,\n GalleryConfig,\n RouteHandler,\n} from \"../types\";\nimport { createGalleryService } from \"../services\";\nimport { createCategoryService } from \"../services/category-service\";\nimport { createGallerySchemas } from \"../validators\";\nimport {\n CategoryInUseError,\n GalleryNotFoundError,\n} from \"../errors\";\nimport {\n parsePagination,\n getSearchParam,\n parseSortKey,\n validateAndParse,\n validateIds,\n} from \"../utils/api-helpers\";\n\nconst VALID_SORT_KEYS = [\n \"sortOrder\",\n \"createdAt\",\n \"updatedAt\",\n \"caption\",\n] as const;\n\ntype SortKey = (typeof VALID_SORT_KEYS)[number];\n\nexport interface GalleryRoutes {\n collection: { GET: RouteHandler; POST: RouteHandler; DELETE: RouteHandler };\n item: { GET: RouteHandler; PUT: RouteHandler; DELETE: RouteHandler };\n publishToggle: { PATCH: RouteHandler };\n bulk: { POST: RouteHandler; PATCH: RouteHandler };\n categoryCollection: { GET: RouteHandler; POST: RouteHandler };\n categoryItem: {\n GET: RouteHandler;\n PUT: RouteHandler;\n DELETE: RouteHandler;\n };\n}\n\nfunction jsonError(message: string, status: number, error?: string): Response {\n return NextResponse.json(\n { success: false, error: error ?? \"Error\", message },\n { status },\n );\n}\n\nfunction callRevalidate(config: GalleryConfig): void {\n if (!config.revalidate || !config.revalidatePaths) return;\n for (const p of config.revalidatePaths) {\n config.revalidate(p);\n }\n}\n\nfunction getAuthorId(config: GalleryConfig, ctx: ApiContext): string | null {\n if (config.authorIdFromContext) {\n try {\n const id = config.authorIdFromContext(ctx);\n return id || null;\n } catch {\n return null;\n }\n }\n return ctx.user?.id ?? null;\n}\n\nfunction getRouteId(ctx: ApiContext): string | null {\n const id = ctx.params?.id;\n return typeof id === \"string\" && id.length > 0 ? id : null;\n}\n\nexport function createGalleryRoutes(config: GalleryConfig): GalleryRoutes {\n const service = createGalleryService(config);\n const categoryService = createCategoryService(config);\n const schemas = createGallerySchemas({\n batchMax: config.limits.batchMax,\n captionMaxLength: config.limits.captionMaxLength ?? 200,\n });\n\n // ── /api/admin/galleries ─────────────────────────────\n\n const collectionGET = config.apiWrapper(async (ctx: ApiContext) => {\n const { page, limit } = parsePagination(ctx.request);\n const { searchParams } = new URL(ctx.request.url);\n const categoryId = getSearchParam(ctx.request, \"categoryId\");\n const publishedRaw = getSearchParam(ctx.request, \"published\");\n const search = getSearchParam(ctx.request, \"search\");\n const sortBy = parseSortKey<SortKey>(\n searchParams,\n VALID_SORT_KEYS,\n \"sortOrder\",\n );\n\n const published =\n publishedRaw === \"true\"\n ? true\n : publishedRaw === \"false\"\n ? false\n : undefined;\n\n const result = await service.listAll({\n page,\n limit,\n categoryId,\n published,\n search,\n sortBy,\n });\n\n return NextResponse.json({ success: true, data: result });\n });\n\n const collectionPOST = config.apiWrapper(async (ctx: ApiContext) => {\n const authorId = getAuthorId(config, ctx);\n if (!authorId) return jsonError(\"authentication required\", 401, \"Unauthorized\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.CreateGallerySchema, body);\n if (!validation.success) return validation.response;\n\n const item = await service.create(validation.data, authorId);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: item }, { status: 201 });\n });\n\n const collectionDELETE = config.apiWrapper(async (ctx: ApiContext) => {\n const body = await ctx.request.json();\n const check = validateIds(body?.ids);\n if (!check.valid) return check.response;\n\n const { count } = await service.removeMany(check.ids);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: { count } });\n });\n\n // ── /api/admin/galleries/[id] ────────────────────────\n\n const itemGET = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n const item = await service.getById(id);\n if (!item) return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n\n return NextResponse.json({ success: true, data: item });\n });\n\n const itemPUT = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.UpdateGallerySchema, body);\n if (!validation.success) return validation.response;\n\n const existing = await service.getById(id);\n if (!existing) return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n\n if (config.permissions?.canEdit) {\n const ok = config.permissions.canEdit(ctx, { authorId: existing.authorId });\n if (!ok) return jsonError(\"forbidden\", 403, \"Forbidden\");\n }\n\n const item = await service.update(id, validation.data);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: item });\n });\n\n const itemDELETE = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n if (config.permissions?.canDelete) {\n const existing = await service.getById(id);\n if (!existing) return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n const ok = config.permissions.canDelete(ctx, {\n authorId: existing.authorId,\n });\n if (!ok) return jsonError(\"forbidden\", 403, \"Forbidden\");\n }\n\n await service.remove(id);\n callRevalidate(config);\n return new NextResponse(null, { status: 204 });\n });\n\n // ── /api/admin/galleries/[id]/publish ────────────────\n\n const publishTogglePATCH = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n if (config.permissions?.canEdit) {\n const existing = await service.getById(id);\n if (!existing) return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n const ok = config.permissions.canEdit(ctx, {\n authorId: existing.authorId,\n });\n if (!ok) return jsonError(\"forbidden\", 403, \"Forbidden\");\n }\n\n try {\n const result = await service.togglePublish(id);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: result });\n } catch (err) {\n // service.togglePublish throws GalleryNotFoundError on missing id — map to 404\n if (err instanceof GalleryNotFoundError) {\n return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n }\n throw err;\n }\n });\n\n // ── /api/admin/galleries/bulk ────────────────────────\n\n const bulkPOST = config.apiWrapper(async (ctx: ApiContext) => {\n const authorId = getAuthorId(config, ctx);\n if (!authorId) return jsonError(\"authentication required\", 401, \"Unauthorized\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.BatchCreateGallerySchema, body);\n if (!validation.success) return validation.response;\n\n const result = await service.createMany(validation.data.items, authorId);\n callRevalidate(config);\n return NextResponse.json(\n { success: true, data: result },\n { status: 201 },\n );\n });\n\n const bulkPATCH = config.apiWrapper(async (ctx: ApiContext) => {\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.BulkUpdateSchema, body);\n if (!validation.success) return validation.response;\n\n const { ids, published, featured } = validation.data;\n let count = 0;\n\n if (published !== undefined) {\n const r = await service.bulkUpdatePublished(ids, published);\n count = r.count;\n }\n if (featured !== undefined) {\n const r = await service.bulkUpdateFeatured(ids, featured);\n count = r.count;\n }\n\n callRevalidate(config);\n return NextResponse.json({ success: true, data: { count } });\n });\n\n // ── /api/admin/gallery-categories ────────────────────\n\n const categoryCollectionGET = config.apiWrapper(async (ctx: ApiContext) => {\n const isActiveRaw = getSearchParam(ctx.request, \"isActive\");\n const isActive =\n isActiveRaw === \"true\"\n ? true\n : isActiveRaw === \"false\"\n ? false\n : undefined;\n\n const items = await categoryService.list(\n isActive === undefined ? undefined : { isActive },\n );\n return NextResponse.json({ success: true, data: items });\n });\n\n const categoryCollectionPOST = config.apiWrapper(async (ctx: ApiContext) => {\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.CreateCategorySchema, body);\n if (!validation.success) return validation.response;\n\n const item = await categoryService.create(validation.data);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: item }, { status: 201 });\n });\n\n // ── /api/admin/gallery-categories/[id] ───────────────\n\n const categoryItemGET = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n const item = await categoryService.getById(id);\n if (!item) return jsonError(\"Category not found\", 404, \"NotFound\");\n return NextResponse.json({ success: true, data: item });\n });\n\n const categoryItemPUT = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.UpdateCategorySchema, body);\n if (!validation.success) return validation.response;\n\n const existing = await categoryService.getById(id);\n if (!existing) return jsonError(\"Category not found\", 404, \"NotFound\");\n\n const item = await categoryService.update(id, validation.data);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: item });\n });\n\n const categoryItemDELETE = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n try {\n await categoryService.remove(id);\n } catch (err) {\n if (err instanceof CategoryInUseError) {\n return jsonError(err.message, 409, \"CategoryInUse\");\n }\n throw err;\n }\n callRevalidate(config);\n return new NextResponse(null, { status: 204 });\n });\n\n return {\n collection: {\n GET: collectionGET,\n POST: collectionPOST,\n DELETE: collectionDELETE,\n },\n item: { GET: itemGET, PUT: itemPUT, DELETE: itemDELETE },\n publishToggle: { PATCH: publishTogglePATCH },\n bulk: { POST: bulkPOST, PATCH: bulkPATCH },\n categoryCollection: {\n GET: categoryCollectionGET,\n POST: categoryCollectionPOST,\n },\n categoryItem: {\n GET: categoryItemGET,\n PUT: categoryItemPUT,\n DELETE: categoryItemDELETE,\n },\n };\n}\n","import { NextResponse } from \"next/server\";\nimport type { z } from \"zod\";\n\ninterface RequestLike {\n url: string;\n}\n\nexport function parsePagination(req: RequestLike): { page: number; limit: number } {\n const { searchParams } = new URL(req.url);\n const rawPage = Number.parseInt(searchParams.get(\"page\") ?? \"1\", 10);\n const rawLimit = Number.parseInt(searchParams.get(\"limit\") ?? \"20\", 10);\n const page = Number.isFinite(rawPage) && rawPage > 0 ? rawPage : 1;\n const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, 100) : 20;\n return { page, limit };\n}\n\nexport function getSearchParam(req: RequestLike, key: string): string | undefined {\n const { searchParams } = new URL(req.url);\n const v = searchParams.get(key);\n return v ?? undefined;\n}\n\nexport type ValidateAndParseResult<T> =\n | { success: true; data: T }\n | { success: false; response: Response };\n\nexport function validateAndParse<T>(\n schema: z.ZodSchema<T>,\n data: unknown,\n): ValidateAndParseResult<T> {\n const parsed = schema.safeParse(data);\n if (parsed.success) return { success: true, data: parsed.data };\n return {\n success: false,\n response: NextResponse.json(\n { success: false, error: \"ValidationError\", details: parsed.error.issues },\n { status: 400 },\n ),\n };\n}\n\nexport type ValidateIdsResult =\n | { valid: true; ids: string[] }\n | { valid: false; response: Response };\n\nexport function validateIds(input: unknown): ValidateIdsResult {\n if (!Array.isArray(input) || input.length === 0) {\n return {\n valid: false,\n response: NextResponse.json(\n { success: false, error: \"InvalidIds\", message: \"ids must be a non-empty array\" },\n { status: 400 },\n ),\n };\n }\n const ids = input.filter((x): x is string => typeof x === \"string\" && x.length > 0);\n if (ids.length === 0) {\n return {\n valid: false,\n response: NextResponse.json(\n { success: false, error: \"InvalidIds\", message: \"ids array contains no valid strings\" },\n { status: 400 },\n ),\n };\n }\n return { valid: true, ids };\n}\n\nexport function parseSortKey<T extends string>(\n searchParams: URLSearchParams,\n allowed: readonly T[],\n fallback: T,\n): T {\n const raw = searchParams.get(\"sortBy\");\n return raw && (allowed as readonly string[]).includes(raw) ? (raw as T) : fallback;\n}\n","/**\n * RSC loaders — spec §9-4.\n *\n * Server Components 가 직접 호출하는 함수. 각 함수는 service 의 대응 메서드를\n * 얇게 감싸기만 한다. host 가 매번 `config` 를 주입해 explicit DI 를 유지한다\n * (setGalleryConfig 의존 회피 — host 의 layout/page 에서 config 를 명시적으로\n * 주입하는 것이 RSC graph 캐싱과 호환성 면에서 더 안전).\n */\nimport type {\n GalleryConfig,\n GalleryListItem,\n PaginatedResult,\n} from \"../types\";\nimport { createGalleryService } from \"../services\";\n\ntype SortKey = \"sortOrder\" | \"createdAt\" | \"updatedAt\" | \"caption\";\n\n/**\n * spec §9-4: `getGalleryItems(config, opts) → PaginatedResult<GalleryListItem>`\n *\n * admin 페이지의 RSC 가 직접 호출. fetch 라운드트립 없이 service 호출.\n */\nexport async function getGalleryItems(\n config: GalleryConfig,\n opts: {\n page?: number;\n limit?: number;\n categoryId?: string;\n published?: boolean;\n search?: string;\n sortBy?: SortKey;\n },\n): Promise<PaginatedResult<GalleryListItem>> {\n const service = createGalleryService(config);\n return service.listAll(opts);\n}\n\n/**\n * spec §9-4: `getFeaturedGalleries(config, limit?) → GalleryListItem[]`\n *\n * 홈 페이지의 모자이크 그리드 등 featured 영역에서 호출.\n */\nexport async function getFeaturedGalleries(\n config: GalleryConfig,\n limit?: number,\n): Promise<GalleryListItem[]> {\n const service = createGalleryService(config);\n return service.listFeatured(limit);\n}\n\n/**\n * spec §9-4: `getRecentGalleries(config, limit) → GalleryListItem[]`\n *\n * 대시보드의 최근 항목 위젯 등에서 호출.\n */\nexport async function getRecentGalleries(\n config: GalleryConfig,\n limit: number,\n): Promise<GalleryListItem[]> {\n const service = createGalleryService(config);\n return service.listRecent(limit);\n}\n\n/**\n * spec §9-4: `getGalleryCount(config, opts?) → number`\n *\n * 대시보드 통계 등에서 호출. `opts.published` 미지정 시 전체 count.\n */\nexport async function getGalleryCount(\n config: GalleryConfig,\n opts?: { published?: boolean },\n): Promise<number> {\n const service = createGalleryService(config);\n return service.count(opts);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-gallery/dist/server/index.js","../../src/services/helpers.ts","../../src/services/category-service.ts","../../src/services/index.ts","../../src/server/route-handlers.ts","../../src/utils/api-helpers.ts","../../src/server/loaders.ts"],"names":["NextResponse"],"mappings":"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","file":"/Users/uni4love/project/workspace/211-withwiz/node-packages/withwiz-gallery/dist/server/index.js","sourcesContent":[null,"import type { PaginatedResult } from \"../types/pagination\";\n\n/**\n * pagination math 를 일관되게 처리. ballet 의 `buildPaginatedResult` 와 동일 시맨틱.\n *\n * - total === 0 일 때 totalPages = 0 (clamp 안 함; UI 에서 \"결과 없음\" 로 처리)\n * - page > totalPages 여도 결과 자체는 caller 의 query 가 결정 — meta 만 계산\n */\nexport function buildPaginatedResult<T>(\n items: T[],\n page: number,\n limit: number,\n total: number,\n): PaginatedResult<T> {\n const totalPages = total === 0 ? 0 : Math.ceil(total / limit);\n return {\n items,\n meta: {\n page,\n limit,\n total,\n totalPages,\n hasNext: page < totalPages,\n hasPrev: page > 1,\n },\n };\n}\n","import type {\n GalleryConfig,\n GalleryCategoryItem,\n CreateCategoryInput,\n UpdateCategoryInput,\n} from \"../types\";\nimport { CategoryInUseError } from \"../errors\";\n\n/**\n * spec §9-2 의 categoryService.\n *\n * 호스트 독립성을 위해 Prisma delegate 는 `config.prisma[modelName]` 패턴으로 접근한다\n * (modelName 기본값 = \"galleryCategory\", gallery 본체 modelName 기본값 = \"gallery\").\n *\n * remove() 는 `onDelete: Restrict` 보강 — 사전 gallery.count() 후 throw.\n * admin UX 가 친화적 에러 메시지를 표시하도록 명시적 throw 를 사용.\n */\nexport function createCategoryService(config: GalleryConfig) {\n const categoryDelegate = () =>\n config.prisma[config.categoryModelName ?? \"galleryCategory\"];\n const galleryDelegate = () => config.prisma[config.modelName ?? \"gallery\"];\n\n async function list(opts?: { isActive?: boolean }): Promise<GalleryCategoryItem[]> {\n const where =\n opts?.isActive !== undefined ? { isActive: opts.isActive } : undefined;\n const rows = await categoryDelegate().findMany({\n ...(where ? { where } : {}),\n orderBy: [{ sortOrder: \"asc\" }, { createdAt: \"asc\" }],\n });\n return rows as GalleryCategoryItem[];\n }\n\n async function getBySlug(slug: string): Promise<GalleryCategoryItem | null> {\n const row = await categoryDelegate().findUnique({ where: { slug } });\n return (row as GalleryCategoryItem | null) ?? null;\n }\n\n async function getById(id: string): Promise<GalleryCategoryItem | null> {\n const row = await categoryDelegate().findUnique({ where: { id } });\n return (row as GalleryCategoryItem | null) ?? null;\n }\n\n async function create(data: CreateCategoryInput): Promise<GalleryCategoryItem> {\n const row = await categoryDelegate().create({ data });\n return row as GalleryCategoryItem;\n }\n\n async function update(\n id: string,\n data: UpdateCategoryInput,\n ): Promise<GalleryCategoryItem> {\n const row = await categoryDelegate().update({ where: { id }, data });\n return row as GalleryCategoryItem;\n }\n\n /**\n * 사용 중 카테고리 (galleries 가 참조) 는 삭제 차단.\n * DB 의 `onDelete: Restrict` 가 최종 방어선이지만, 친화적 에러를 위해 사전 count.\n */\n async function remove(id: string): Promise<void> {\n const inUse = await galleryDelegate().count({ where: { categoryId: id } });\n if (inUse > 0) {\n throw new CategoryInUseError(id, inUse);\n }\n await categoryDelegate().delete({ where: { id } });\n }\n\n /**\n * ids 배열 순서대로 sortOrder = 0..N-1 로 갱신.\n * 단일 mutation 묶음 — $transaction 사용 (배열 형태).\n */\n async function reorder(ids: string[]): Promise<void> {\n const ops = ids.map((id, idx) =>\n categoryDelegate().update({ where: { id }, data: { sortOrder: idx } }),\n );\n await config.prisma.$transaction(ops);\n }\n\n return { list, getBySlug, getById, create, update, remove, reorder };\n}\n\nexport type CategoryService = ReturnType<typeof createCategoryService>;\n","import type {\n GalleryConfig,\n GalleryDetail,\n GalleryListItem,\n CreateGalleryInput,\n UpdateGalleryInput,\n PaginatedResult,\n} from \"../types\";\nimport { GalleryNotFoundError } from \"../errors\";\nimport { buildPaginatedResult } from \"./helpers\";\n\nexport { buildPaginatedResult } from \"./helpers\";\nexport { createCategoryService } from \"./category-service\";\nexport type { CategoryService } from \"./category-service\";\n\ntype SortKey = \"sortOrder\" | \"createdAt\" | \"updatedAt\" | \"caption\";\n\n/**\n * spec §9-2 의 createGalleryService.\n *\n * 핵심 규칙:\n * - Prisma delegate 는 `config.prisma[config.modelName ?? \"gallery\"]` 패턴.\n * - `include: { category: true }` 만 사용. **author include 금지** (Gallery 모델에 author 관계 없음, §3 호스트 독립 원칙).\n * - 삭제 시 `config.storage` 가 isEnabled() true 면 collectKeys → deleteKeys.\n * - `revalidate` 는 service 에서 호출하지 않음 (route handler 책임).\n */\nexport function createGalleryService(config: GalleryConfig) {\n const galleryDelegate = () => config.prisma[config.modelName ?? \"gallery\"];\n const baseInclude = { category: true } as const;\n\n function orderByFor(sortBy: SortKey) {\n switch (sortBy) {\n case \"sortOrder\":\n return [{ sortOrder: \"asc\" as const }, { createdAt: \"desc\" as const }];\n case \"caption\":\n return { caption: \"asc\" as const };\n case \"createdAt\":\n case \"updatedAt\":\n return { [sortBy]: \"desc\" as const };\n }\n }\n\n // ── Public-facing read methods ─────────────────────\n\n async function listFeatured(limit?: number): Promise<GalleryListItem[]> {\n const rows = await galleryDelegate().findMany({\n where: { published: true, featured: true },\n include: baseInclude,\n orderBy: [{ sortOrder: \"asc\" }, { createdAt: \"desc\" }],\n ...(limit ? { take: limit } : {}),\n });\n return rows as GalleryListItem[];\n }\n\n async function listPublished(limit?: number): Promise<GalleryListItem[]> {\n const rows = await galleryDelegate().findMany({\n where: { published: true },\n include: baseInclude,\n orderBy: [{ sortOrder: \"asc\" }, { createdAt: \"desc\" }],\n ...(limit ? { take: limit } : {}),\n });\n return rows as GalleryListItem[];\n }\n\n async function listPublishedByCategory(\n categorySlug: string,\n limit?: number,\n ): Promise<GalleryListItem[]> {\n const rows = await galleryDelegate().findMany({\n where: { published: true, category: { slug: categorySlug } },\n include: baseInclude,\n orderBy: [{ sortOrder: \"asc\" }, { createdAt: \"desc\" }],\n ...(limit ? { take: limit } : {}),\n });\n return rows as GalleryListItem[];\n }\n\n // ── Admin list / detail ────────────────────────────\n\n async function listAll(opts: {\n page?: number;\n limit?: number;\n categoryId?: string;\n published?: boolean;\n search?: string;\n sortBy?: SortKey;\n }): Promise<PaginatedResult<GalleryListItem>> {\n const page = opts.page ?? 1;\n const limit = opts.limit ?? 20;\n const sortBy = opts.sortBy ?? \"sortOrder\";\n const skip = (page - 1) * limit;\n\n const where: Record<string, unknown> = {};\n if (opts.categoryId) where.categoryId = opts.categoryId;\n if (opts.published !== undefined) where.published = opts.published;\n if (opts.search) where.caption = { contains: opts.search, mode: \"insensitive\" };\n\n const [items, total] = await Promise.all([\n galleryDelegate().findMany({\n where,\n include: baseInclude,\n orderBy: orderByFor(sortBy),\n skip,\n take: limit,\n }),\n galleryDelegate().count({ where }),\n ]);\n\n return buildPaginatedResult(items as GalleryListItem[], page, limit, total);\n }\n\n async function getById(id: string): Promise<GalleryDetail | null> {\n const row = await galleryDelegate().findUnique({\n where: { id },\n include: baseInclude,\n });\n return (row as GalleryDetail | null) ?? null;\n }\n\n /**\n * bulk 권한 검사용 — ids 에 해당하는 row 의 {id, authorId} 만 조회.\n * 존재하지 않는 id 는 결과에서 빠진다 (caller 가 길이 비교로 판단).\n */\n async function getAuthorIds(\n ids: string[],\n ): Promise<Array<{ id: string; authorId: string }>> {\n const rows = await galleryDelegate().findMany({\n where: { id: { in: ids } },\n select: { id: true, authorId: true },\n });\n return rows as Array<{ id: string; authorId: string }>;\n }\n\n // ── Mutations ──────────────────────────────────────\n\n async function create(\n data: CreateGalleryInput,\n authorId: string,\n ): Promise<GalleryDetail> {\n const row = await galleryDelegate().create({\n data: {\n imageUrl: data.imageUrl,\n imageKey: data.imageKey ?? null,\n caption: data.caption ?? null,\n categoryId: data.categoryId,\n sortOrder: data.sortOrder ?? 0,\n featured: data.featured ?? false,\n published: data.published ?? false,\n authorId,\n },\n include: baseInclude,\n });\n return row as GalleryDetail;\n }\n\n async function createMany(\n items: CreateGalleryInput[],\n authorId: string,\n ): Promise<{ count: number }> {\n const result = await galleryDelegate().createMany({\n data: items.map((it) => ({\n imageUrl: it.imageUrl,\n imageKey: it.imageKey ?? null,\n caption: it.caption ?? null,\n categoryId: it.categoryId,\n sortOrder: it.sortOrder ?? 0,\n featured: it.featured ?? false,\n published: it.published ?? false,\n authorId,\n })),\n });\n return { count: result.count };\n }\n\n async function update(\n id: string,\n data: UpdateGalleryInput,\n ): Promise<GalleryDetail> {\n const patch: Record<string, unknown> = {};\n if (data.imageUrl !== undefined) patch.imageUrl = data.imageUrl;\n if (data.imageKey !== undefined) patch.imageKey = data.imageKey ?? null;\n if (data.caption !== undefined) patch.caption = data.caption ?? null;\n if (data.categoryId !== undefined) patch.categoryId = data.categoryId;\n if (data.sortOrder !== undefined) patch.sortOrder = data.sortOrder;\n if (data.featured !== undefined) patch.featured = data.featured;\n if (data.published !== undefined) patch.published = data.published;\n\n const row = await galleryDelegate().update({\n where: { id },\n data: patch,\n include: baseInclude,\n });\n return row as GalleryDetail;\n }\n\n async function remove(id: string): Promise<void> {\n const storageEnabled = config.storage?.isEnabled?.() === true;\n let imageKey: string | null = null;\n if (storageEnabled) {\n const row = (await galleryDelegate().findUnique({\n where: { id },\n select: { imageKey: true },\n })) as { imageKey: string | null } | null;\n imageKey = row?.imageKey ?? null;\n }\n await galleryDelegate().delete({ where: { id } });\n if (storageEnabled && imageKey && config.storage) {\n const keys = config.storage.collectKeys(imageKey);\n if (keys.length > 0) await config.storage.deleteKeys(keys);\n }\n }\n\n async function removeMany(ids: string[]): Promise<{ count: number }> {\n const storageEnabled = config.storage?.isEnabled?.() === true;\n let imageKeys: string[] = [];\n if (storageEnabled) {\n const rows = (await galleryDelegate().findMany({\n where: { id: { in: ids } },\n select: { imageKey: true },\n })) as Array<{ imageKey: string | null }>;\n imageKeys = rows\n .map((r) => r.imageKey)\n .filter((k): k is string => typeof k === \"string\" && k.length > 0);\n }\n const result = await galleryDelegate().deleteMany({ where: { id: { in: ids } } });\n if (storageEnabled && imageKeys.length > 0 && config.storage) {\n const allKeys = imageKeys.flatMap((k) => config.storage!.collectKeys(k));\n const uniqueKeys = [...new Set(allKeys)];\n if (uniqueKeys.length > 0) await config.storage.deleteKeys(uniqueKeys);\n }\n return { count: result.count };\n }\n\n async function bulkUpdatePublished(\n ids: string[],\n published: boolean,\n ): Promise<{ count: number }> {\n const result = await galleryDelegate().updateMany({\n where: { id: { in: ids } },\n data: { published, updatedAt: new Date() },\n });\n return { count: result.count };\n }\n\n async function bulkUpdateFeatured(\n ids: string[],\n featured: boolean,\n ): Promise<{ count: number }> {\n const result = await galleryDelegate().updateMany({\n where: { id: { in: ids } },\n data: { featured, updatedAt: new Date() },\n });\n return { count: result.count };\n }\n\n async function togglePublish(id: string): Promise<GalleryDetail> {\n const current = (await galleryDelegate().findUnique({\n where: { id },\n select: { published: true },\n })) as { published: boolean } | null;\n if (!current) {\n throw new GalleryNotFoundError(id);\n }\n const row = await galleryDelegate().update({\n where: { id },\n data: { published: !current.published },\n include: baseInclude,\n });\n return row as GalleryDetail;\n }\n\n async function count(opts?: { published?: boolean }): Promise<number> {\n const where = opts?.published !== undefined ? { published: opts.published } : undefined;\n const n = await galleryDelegate().count(where ? { where } : {});\n return n as number;\n }\n\n async function listRecent(limit: number): Promise<GalleryListItem[]> {\n const rows = await galleryDelegate().findMany({\n include: baseInclude,\n orderBy: { createdAt: \"desc\" },\n take: limit,\n });\n return rows as GalleryListItem[];\n }\n\n return {\n listFeatured,\n listPublished,\n listPublishedByCategory,\n listAll,\n getById,\n getAuthorIds,\n create,\n createMany,\n update,\n remove,\n removeMany,\n bulkUpdatePublished,\n bulkUpdateFeatured,\n togglePublish,\n count,\n listRecent,\n };\n}\n\nexport type GalleryService = ReturnType<typeof createGalleryService>;\n","/**\n * Route handler factory — spec §9-3.\n *\n * `createGalleryRoutes(config)` 가 host 의 `apiWrapper` 로 감싼 9 개 라우트를 반환한다.\n * host 는 각 라우트 파일에서 `export const { GET, POST } = galleryRoutes.collection` 식으로 사용.\n *\n * 설계 원칙:\n * - 모든 mutation 종료 직전 `config.revalidate?.(path)` 를 `config.revalidatePaths` 각 path 에 대해 호출.\n * - `config.permissions?.canEdit/canDelete` 가 함수면 호출 → false 시 403 반환.\n * 미설정이면 admin 전원 모든 권한 (spec §16 v0.1 정책).\n * - bulk (collection DELETE / bulk PATCH) 도 동일 훅을 대상 전원에 적용한다.\n * 하나라도 거부되면 전체 403 (부분 성공 없음). 존재하지 않는 id 가 섞이면 404.\n * - `config.permissions?.canManageCategories` 가 함수면 카테고리 CUD 에 적용.\n * - `ctx.params?.id` 는 host 미들웨어가 채워준다고 가정 (spec §6-1).\n * - 카테고리 `remove` 의 in-use 에러는 service throw → handler 가 잡아 409 반환.\n */\nimport { NextResponse } from \"next/server\";\nimport type {\n ApiContext,\n GalleryConfig,\n RouteHandler,\n} from \"../types\";\nimport { createGalleryService } from \"../services\";\nimport { createCategoryService } from \"../services/category-service\";\nimport { createGallerySchemas } from \"../validators\";\nimport {\n CategoryInUseError,\n GalleryNotFoundError,\n} from \"../errors\";\nimport {\n parsePagination,\n getSearchParam,\n parseSortKey,\n validateAndParse,\n validateIds,\n} from \"../utils/api-helpers\";\n\nconst VALID_SORT_KEYS = [\n \"sortOrder\",\n \"createdAt\",\n \"updatedAt\",\n \"caption\",\n] as const;\n\ntype SortKey = (typeof VALID_SORT_KEYS)[number];\n\nexport interface GalleryRoutes {\n collection: { GET: RouteHandler; POST: RouteHandler; DELETE: RouteHandler };\n item: { GET: RouteHandler; PUT: RouteHandler; DELETE: RouteHandler };\n publishToggle: { PATCH: RouteHandler };\n bulk: { POST: RouteHandler; PATCH: RouteHandler };\n categoryCollection: { GET: RouteHandler; POST: RouteHandler };\n categoryItem: {\n GET: RouteHandler;\n PUT: RouteHandler;\n DELETE: RouteHandler;\n };\n}\n\nfunction jsonError(message: string, status: number, error?: string): Response {\n return NextResponse.json(\n { success: false, error: error ?? \"Error\", message },\n { status },\n );\n}\n\nfunction callRevalidate(config: GalleryConfig): void {\n if (!config.revalidate || !config.revalidatePaths) return;\n for (const p of config.revalidatePaths) {\n config.revalidate(p);\n }\n}\n\nfunction getAuthorId(config: GalleryConfig, ctx: ApiContext): string | null {\n if (config.authorIdFromContext) {\n try {\n const id = config.authorIdFromContext(ctx);\n return id || null;\n } catch {\n return null;\n }\n }\n return ctx.user?.id ?? null;\n}\n\nfunction getRouteId(ctx: ApiContext): string | null {\n const id = ctx.params?.id;\n return typeof id === \"string\" && id.length > 0 ? id : null;\n}\n\nconst DEFAULT_SEARCH_MAX_LENGTH = 100;\n\nfunction canManageCategories(config: GalleryConfig, ctx: ApiContext): boolean {\n const fn = config.permissions?.canManageCategories;\n return fn ? fn(ctx) === true : true;\n}\n\ntype BulkPermissionCheck =\n | { ok: true }\n | { ok: false; response: Response };\n\n/**\n * bulk 대상 전원에 대해 permission 훅을 적용한다.\n * - 훅 미설정: 통과.\n * - 대상 중 존재하지 않는 id: 404 (권한 검사 대상이 불명확하므로 거부).\n * - 하나라도 거부: 403.\n */\nasync function checkBulkPermission(\n ctx: ApiContext,\n ids: string[],\n hook: ((ctx: ApiContext, gallery: { authorId: string }) => boolean) | undefined,\n loadAuthorIds: (ids: string[]) => Promise<Array<{ id: string; authorId: string }>>,\n): Promise<BulkPermissionCheck> {\n if (!hook) return { ok: true };\n const unique = [...new Set(ids)];\n const rows = await loadAuthorIds(unique);\n if (rows.length !== unique.length) {\n return {\n ok: false,\n response: jsonError(\"one or more gallery items not found\", 404, \"NotFound\"),\n };\n }\n for (const row of rows) {\n if (!hook(ctx, { authorId: row.authorId })) {\n return { ok: false, response: jsonError(\"forbidden\", 403, \"Forbidden\") };\n }\n }\n return { ok: true };\n}\n\nexport function createGalleryRoutes(config: GalleryConfig): GalleryRoutes {\n const service = createGalleryService(config);\n const categoryService = createCategoryService(config);\n const schemas = createGallerySchemas({\n batchMax: config.limits.batchMax,\n captionMaxLength: config.limits.captionMaxLength ?? 200,\n imageUrlProtocols: config.validation?.imageUrlProtocols,\n imageUrlHosts: config.validation?.imageUrlHosts,\n imageKeyPattern: config.validation?.imageKeyPattern,\n });\n const searchMaxLength =\n config.validation?.searchMaxLength ?? DEFAULT_SEARCH_MAX_LENGTH;\n\n // ── /api/admin/galleries ─────────────────────────────\n\n const collectionGET = config.apiWrapper(async (ctx: ApiContext) => {\n const { page, limit } = parsePagination(ctx.request);\n const { searchParams } = new URL(ctx.request.url);\n const categoryId = getSearchParam(ctx.request, \"categoryId\");\n const publishedRaw = getSearchParam(ctx.request, \"published\");\n const searchRaw = getSearchParam(ctx.request, \"search\")?.trim();\n const search = searchRaw ? searchRaw.slice(0, searchMaxLength) : undefined;\n const sortBy = parseSortKey<SortKey>(\n searchParams,\n VALID_SORT_KEYS,\n \"sortOrder\",\n );\n\n const published =\n publishedRaw === \"true\"\n ? true\n : publishedRaw === \"false\"\n ? false\n : undefined;\n\n const result = await service.listAll({\n page,\n limit,\n categoryId,\n published,\n search,\n sortBy,\n });\n\n return NextResponse.json({ success: true, data: result });\n });\n\n const collectionPOST = config.apiWrapper(async (ctx: ApiContext) => {\n const authorId = getAuthorId(config, ctx);\n if (!authorId) return jsonError(\"authentication required\", 401, \"Unauthorized\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.CreateGallerySchema, body);\n if (!validation.success) return validation.response;\n\n const item = await service.create(validation.data, authorId);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: item }, { status: 201 });\n });\n\n const collectionDELETE = config.apiWrapper(async (ctx: ApiContext) => {\n const body = await ctx.request.json();\n const check = validateIds(body?.ids);\n if (!check.valid) return check.response;\n if (check.ids.length > config.limits.batchMax) {\n return jsonError(\n `ids exceeds batchMax (${config.limits.batchMax})`,\n 400,\n \"InvalidIds\",\n );\n }\n\n const perm = await checkBulkPermission(\n ctx,\n check.ids,\n config.permissions?.canDelete,\n service.getAuthorIds,\n );\n if (!perm.ok) return perm.response;\n\n const { count } = await service.removeMany(check.ids);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: { count } });\n });\n\n // ── /api/admin/galleries/[id] ────────────────────────\n\n const itemGET = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n const item = await service.getById(id);\n if (!item) return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n\n return NextResponse.json({ success: true, data: item });\n });\n\n const itemPUT = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.UpdateGallerySchema, body);\n if (!validation.success) return validation.response;\n\n const existing = await service.getById(id);\n if (!existing) return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n\n if (config.permissions?.canEdit) {\n const ok = config.permissions.canEdit(ctx, { authorId: existing.authorId });\n if (!ok) return jsonError(\"forbidden\", 403, \"Forbidden\");\n }\n\n const item = await service.update(id, validation.data);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: item });\n });\n\n const itemDELETE = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n if (config.permissions?.canDelete) {\n const existing = await service.getById(id);\n if (!existing) return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n const ok = config.permissions.canDelete(ctx, {\n authorId: existing.authorId,\n });\n if (!ok) return jsonError(\"forbidden\", 403, \"Forbidden\");\n }\n\n await service.remove(id);\n callRevalidate(config);\n return new NextResponse(null, { status: 204 });\n });\n\n // ── /api/admin/galleries/[id]/publish ────────────────\n\n const publishTogglePATCH = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n if (config.permissions?.canEdit) {\n const existing = await service.getById(id);\n if (!existing) return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n const ok = config.permissions.canEdit(ctx, {\n authorId: existing.authorId,\n });\n if (!ok) return jsonError(\"forbidden\", 403, \"Forbidden\");\n }\n\n try {\n const result = await service.togglePublish(id);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: result });\n } catch (err) {\n // service.togglePublish throws GalleryNotFoundError on missing id — map to 404\n if (err instanceof GalleryNotFoundError) {\n return jsonError(\"Gallery item not found\", 404, \"NotFound\");\n }\n throw err;\n }\n });\n\n // ── /api/admin/galleries/bulk ────────────────────────\n\n const bulkPOST = config.apiWrapper(async (ctx: ApiContext) => {\n const authorId = getAuthorId(config, ctx);\n if (!authorId) return jsonError(\"authentication required\", 401, \"Unauthorized\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.BatchCreateGallerySchema, body);\n if (!validation.success) return validation.response;\n\n const result = await service.createMany(validation.data.items, authorId);\n callRevalidate(config);\n return NextResponse.json(\n { success: true, data: result },\n { status: 201 },\n );\n });\n\n const bulkPATCH = config.apiWrapper(async (ctx: ApiContext) => {\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.BulkUpdateSchema, body);\n if (!validation.success) return validation.response;\n\n const { ids, published, featured } = validation.data;\n\n const perm = await checkBulkPermission(\n ctx,\n ids,\n config.permissions?.canEdit,\n service.getAuthorIds,\n );\n if (!perm.ok) return perm.response;\n\n let count = 0;\n\n if (published !== undefined) {\n const r = await service.bulkUpdatePublished(ids, published);\n count = r.count;\n }\n if (featured !== undefined) {\n const r = await service.bulkUpdateFeatured(ids, featured);\n count = r.count;\n }\n\n callRevalidate(config);\n return NextResponse.json({ success: true, data: { count } });\n });\n\n // ── /api/admin/gallery-categories ────────────────────\n\n const categoryCollectionGET = config.apiWrapper(async (ctx: ApiContext) => {\n const isActiveRaw = getSearchParam(ctx.request, \"isActive\");\n const isActive =\n isActiveRaw === \"true\"\n ? true\n : isActiveRaw === \"false\"\n ? false\n : undefined;\n\n const items = await categoryService.list(\n isActive === undefined ? undefined : { isActive },\n );\n return NextResponse.json({ success: true, data: items });\n });\n\n const categoryCollectionPOST = config.apiWrapper(async (ctx: ApiContext) => {\n if (!canManageCategories(config, ctx)) return jsonError(\"forbidden\", 403, \"Forbidden\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.CreateCategorySchema, body);\n if (!validation.success) return validation.response;\n\n const item = await categoryService.create(validation.data);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: item }, { status: 201 });\n });\n\n // ── /api/admin/gallery-categories/[id] ───────────────\n\n const categoryItemGET = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n\n const item = await categoryService.getById(id);\n if (!item) return jsonError(\"Category not found\", 404, \"NotFound\");\n return NextResponse.json({ success: true, data: item });\n });\n\n const categoryItemPUT = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n if (!canManageCategories(config, ctx)) return jsonError(\"forbidden\", 403, \"Forbidden\");\n\n const body = await ctx.request.json();\n const validation = validateAndParse(schemas.UpdateCategorySchema, body);\n if (!validation.success) return validation.response;\n\n const existing = await categoryService.getById(id);\n if (!existing) return jsonError(\"Category not found\", 404, \"NotFound\");\n\n const item = await categoryService.update(id, validation.data);\n callRevalidate(config);\n return NextResponse.json({ success: true, data: item });\n });\n\n const categoryItemDELETE = config.apiWrapper(async (ctx: ApiContext) => {\n const id = getRouteId(ctx);\n if (!id) return jsonError(\"missing route param: id\", 400, \"InvalidParams\");\n if (!canManageCategories(config, ctx)) return jsonError(\"forbidden\", 403, \"Forbidden\");\n\n try {\n await categoryService.remove(id);\n } catch (err) {\n if (err instanceof CategoryInUseError) {\n return jsonError(err.message, 409, \"CategoryInUse\");\n }\n throw err;\n }\n callRevalidate(config);\n return new NextResponse(null, { status: 204 });\n });\n\n return {\n collection: {\n GET: collectionGET,\n POST: collectionPOST,\n DELETE: collectionDELETE,\n },\n item: { GET: itemGET, PUT: itemPUT, DELETE: itemDELETE },\n publishToggle: { PATCH: publishTogglePATCH },\n bulk: { POST: bulkPOST, PATCH: bulkPATCH },\n categoryCollection: {\n GET: categoryCollectionGET,\n POST: categoryCollectionPOST,\n },\n categoryItem: {\n GET: categoryItemGET,\n PUT: categoryItemPUT,\n DELETE: categoryItemDELETE,\n },\n };\n}\n","import { NextResponse } from \"next/server\";\nimport type { z } from \"zod\";\n\ninterface RequestLike {\n url: string;\n}\n\nexport function parsePagination(req: RequestLike): { page: number; limit: number } {\n const { searchParams } = new URL(req.url);\n const rawPage = Number.parseInt(searchParams.get(\"page\") ?? \"1\", 10);\n const rawLimit = Number.parseInt(searchParams.get(\"limit\") ?? \"20\", 10);\n const page = Number.isFinite(rawPage) && rawPage > 0 ? rawPage : 1;\n const limit = Number.isFinite(rawLimit) && rawLimit > 0 ? Math.min(rawLimit, 100) : 20;\n return { page, limit };\n}\n\nexport function getSearchParam(req: RequestLike, key: string): string | undefined {\n const { searchParams } = new URL(req.url);\n const v = searchParams.get(key);\n return v ?? undefined;\n}\n\nexport type ValidateAndParseResult<T> =\n | { success: true; data: T }\n | { success: false; response: Response };\n\nexport function validateAndParse<T>(\n schema: z.ZodSchema<T>,\n data: unknown,\n): ValidateAndParseResult<T> {\n const parsed = schema.safeParse(data);\n if (parsed.success) return { success: true, data: parsed.data };\n return {\n success: false,\n response: NextResponse.json(\n { success: false, error: \"ValidationError\", details: parsed.error.issues },\n { status: 400 },\n ),\n };\n}\n\nexport type ValidateIdsResult =\n | { valid: true; ids: string[] }\n | { valid: false; response: Response };\n\nexport function validateIds(input: unknown): ValidateIdsResult {\n if (!Array.isArray(input) || input.length === 0) {\n return {\n valid: false,\n response: NextResponse.json(\n { success: false, error: \"InvalidIds\", message: \"ids must be a non-empty array\" },\n { status: 400 },\n ),\n };\n }\n const ids = input.filter((x): x is string => typeof x === \"string\" && x.length > 0);\n if (ids.length === 0) {\n return {\n valid: false,\n response: NextResponse.json(\n { success: false, error: \"InvalidIds\", message: \"ids array contains no valid strings\" },\n { status: 400 },\n ),\n };\n }\n return { valid: true, ids };\n}\n\nexport function parseSortKey<T extends string>(\n searchParams: URLSearchParams,\n allowed: readonly T[],\n fallback: T,\n): T {\n const raw = searchParams.get(\"sortBy\");\n return raw && (allowed as readonly string[]).includes(raw) ? (raw as T) : fallback;\n}\n","/**\n * RSC loaders — spec §9-4.\n *\n * Server Components 가 직접 호출하는 함수. 각 함수는 service 의 대응 메서드를\n * 얇게 감싸기만 한다. host 가 매번 `config` 를 주입해 explicit DI 를 유지한다\n * (setGalleryConfig 의존 회피 — host 의 layout/page 에서 config 를 명시적으로\n * 주입하는 것이 RSC graph 캐싱과 호환성 면에서 더 안전).\n */\nimport type {\n GalleryConfig,\n GalleryListItem,\n PaginatedResult,\n} from \"../types\";\nimport { createGalleryService } from \"../services\";\n\ntype SortKey = \"sortOrder\" | \"createdAt\" | \"updatedAt\" | \"caption\";\n\n/**\n * spec §9-4: `getGalleryItems(config, opts) → PaginatedResult<GalleryListItem>`\n *\n * admin 페이지의 RSC 가 직접 호출. fetch 라운드트립 없이 service 호출.\n */\nexport async function getGalleryItems(\n config: GalleryConfig,\n opts: {\n page?: number;\n limit?: number;\n categoryId?: string;\n published?: boolean;\n search?: string;\n sortBy?: SortKey;\n },\n): Promise<PaginatedResult<GalleryListItem>> {\n const service = createGalleryService(config);\n return service.listAll(opts);\n}\n\n/**\n * spec §9-4: `getFeaturedGalleries(config, limit?) → GalleryListItem[]`\n *\n * 홈 페이지의 모자이크 그리드 등 featured 영역에서 호출.\n */\nexport async function getFeaturedGalleries(\n config: GalleryConfig,\n limit?: number,\n): Promise<GalleryListItem[]> {\n const service = createGalleryService(config);\n return service.listFeatured(limit);\n}\n\n/**\n * spec §9-4: `getRecentGalleries(config, limit) → GalleryListItem[]`\n *\n * 대시보드의 최근 항목 위젯 등에서 호출.\n */\nexport async function getRecentGalleries(\n config: GalleryConfig,\n limit: number,\n): Promise<GalleryListItem[]> {\n const service = createGalleryService(config);\n return service.listRecent(limit);\n}\n\n/**\n * spec §9-4: `getGalleryCount(config, opts?) → number`\n *\n * 대시보드 통계 등에서 호출. `opts.published` 미지정 시 전체 count.\n */\nexport async function getGalleryCount(\n config: GalleryConfig,\n opts?: { published?: boolean },\n): Promise<number> {\n const service = createGalleryService(config);\n return service.count(opts);\n}\n"]}
|
package/dist/server/index.mjs
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "../chunk-ZEZCUJJD.mjs";
|
|
12
12
|
import {
|
|
13
13
|
createGallerySchemas
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-IEXSUEDO.mjs";
|
|
15
15
|
|
|
16
16
|
// src/services/helpers.ts
|
|
17
17
|
function buildPaginatedResult(items, page, limit, total) {
|
|
@@ -143,6 +143,13 @@ function createGalleryService(config) {
|
|
|
143
143
|
});
|
|
144
144
|
return row ?? null;
|
|
145
145
|
}
|
|
146
|
+
async function getAuthorIds(ids) {
|
|
147
|
+
const rows = await galleryDelegate().findMany({
|
|
148
|
+
where: { id: { in: ids } },
|
|
149
|
+
select: { id: true, authorId: true }
|
|
150
|
+
});
|
|
151
|
+
return rows;
|
|
152
|
+
}
|
|
146
153
|
async function create(data, authorId) {
|
|
147
154
|
const row = await galleryDelegate().create({
|
|
148
155
|
data: {
|
|
@@ -272,6 +279,7 @@ function createGalleryService(config) {
|
|
|
272
279
|
listPublishedByCategory,
|
|
273
280
|
listAll,
|
|
274
281
|
getById,
|
|
282
|
+
getAuthorIds,
|
|
275
283
|
create,
|
|
276
284
|
createMany,
|
|
277
285
|
update,
|
|
@@ -375,19 +383,46 @@ function getRouteId(ctx) {
|
|
|
375
383
|
const id = ctx.params?.id;
|
|
376
384
|
return typeof id === "string" && id.length > 0 ? id : null;
|
|
377
385
|
}
|
|
386
|
+
var DEFAULT_SEARCH_MAX_LENGTH = 100;
|
|
387
|
+
function canManageCategories(config, ctx) {
|
|
388
|
+
const fn = config.permissions?.canManageCategories;
|
|
389
|
+
return fn ? fn(ctx) === true : true;
|
|
390
|
+
}
|
|
391
|
+
async function checkBulkPermission(ctx, ids, hook, loadAuthorIds) {
|
|
392
|
+
if (!hook) return { ok: true };
|
|
393
|
+
const unique = [...new Set(ids)];
|
|
394
|
+
const rows = await loadAuthorIds(unique);
|
|
395
|
+
if (rows.length !== unique.length) {
|
|
396
|
+
return {
|
|
397
|
+
ok: false,
|
|
398
|
+
response: jsonError("one or more gallery items not found", 404, "NotFound")
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
for (const row of rows) {
|
|
402
|
+
if (!hook(ctx, { authorId: row.authorId })) {
|
|
403
|
+
return { ok: false, response: jsonError("forbidden", 403, "Forbidden") };
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return { ok: true };
|
|
407
|
+
}
|
|
378
408
|
function createGalleryRoutes(config) {
|
|
379
409
|
const service = createGalleryService(config);
|
|
380
410
|
const categoryService = createCategoryService(config);
|
|
381
411
|
const schemas = createGallerySchemas({
|
|
382
412
|
batchMax: config.limits.batchMax,
|
|
383
|
-
captionMaxLength: config.limits.captionMaxLength ?? 200
|
|
413
|
+
captionMaxLength: config.limits.captionMaxLength ?? 200,
|
|
414
|
+
imageUrlProtocols: config.validation?.imageUrlProtocols,
|
|
415
|
+
imageUrlHosts: config.validation?.imageUrlHosts,
|
|
416
|
+
imageKeyPattern: config.validation?.imageKeyPattern
|
|
384
417
|
});
|
|
418
|
+
const searchMaxLength = config.validation?.searchMaxLength ?? DEFAULT_SEARCH_MAX_LENGTH;
|
|
385
419
|
const collectionGET = config.apiWrapper(async (ctx) => {
|
|
386
420
|
const { page, limit } = parsePagination(ctx.request);
|
|
387
421
|
const { searchParams } = new URL(ctx.request.url);
|
|
388
422
|
const categoryId = getSearchParam(ctx.request, "categoryId");
|
|
389
423
|
const publishedRaw = getSearchParam(ctx.request, "published");
|
|
390
|
-
const
|
|
424
|
+
const searchRaw = getSearchParam(ctx.request, "search")?.trim();
|
|
425
|
+
const search = searchRaw ? searchRaw.slice(0, searchMaxLength) : void 0;
|
|
391
426
|
const sortBy = parseSortKey(
|
|
392
427
|
searchParams,
|
|
393
428
|
VALID_SORT_KEYS,
|
|
@@ -418,6 +453,20 @@ function createGalleryRoutes(config) {
|
|
|
418
453
|
const body = await ctx.request.json();
|
|
419
454
|
const check = validateIds(body?.ids);
|
|
420
455
|
if (!check.valid) return check.response;
|
|
456
|
+
if (check.ids.length > config.limits.batchMax) {
|
|
457
|
+
return jsonError(
|
|
458
|
+
`ids exceeds batchMax (${config.limits.batchMax})`,
|
|
459
|
+
400,
|
|
460
|
+
"InvalidIds"
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
const perm = await checkBulkPermission(
|
|
464
|
+
ctx,
|
|
465
|
+
check.ids,
|
|
466
|
+
config.permissions?.canDelete,
|
|
467
|
+
service.getAuthorIds
|
|
468
|
+
);
|
|
469
|
+
if (!perm.ok) return perm.response;
|
|
421
470
|
const { count } = await service.removeMany(check.ids);
|
|
422
471
|
callRevalidate(config);
|
|
423
472
|
return NextResponse2.json({ success: true, data: { count } });
|
|
@@ -500,6 +549,13 @@ function createGalleryRoutes(config) {
|
|
|
500
549
|
const validation = validateAndParse(schemas.BulkUpdateSchema, body);
|
|
501
550
|
if (!validation.success) return validation.response;
|
|
502
551
|
const { ids, published, featured } = validation.data;
|
|
552
|
+
const perm = await checkBulkPermission(
|
|
553
|
+
ctx,
|
|
554
|
+
ids,
|
|
555
|
+
config.permissions?.canEdit,
|
|
556
|
+
service.getAuthorIds
|
|
557
|
+
);
|
|
558
|
+
if (!perm.ok) return perm.response;
|
|
503
559
|
let count = 0;
|
|
504
560
|
if (published !== void 0) {
|
|
505
561
|
const r = await service.bulkUpdatePublished(ids, published);
|
|
@@ -521,6 +577,7 @@ function createGalleryRoutes(config) {
|
|
|
521
577
|
return NextResponse2.json({ success: true, data: items });
|
|
522
578
|
});
|
|
523
579
|
const categoryCollectionPOST = config.apiWrapper(async (ctx) => {
|
|
580
|
+
if (!canManageCategories(config, ctx)) return jsonError("forbidden", 403, "Forbidden");
|
|
524
581
|
const body = await ctx.request.json();
|
|
525
582
|
const validation = validateAndParse(schemas.CreateCategorySchema, body);
|
|
526
583
|
if (!validation.success) return validation.response;
|
|
@@ -538,6 +595,7 @@ function createGalleryRoutes(config) {
|
|
|
538
595
|
const categoryItemPUT = config.apiWrapper(async (ctx) => {
|
|
539
596
|
const id = getRouteId(ctx);
|
|
540
597
|
if (!id) return jsonError("missing route param: id", 400, "InvalidParams");
|
|
598
|
+
if (!canManageCategories(config, ctx)) return jsonError("forbidden", 403, "Forbidden");
|
|
541
599
|
const body = await ctx.request.json();
|
|
542
600
|
const validation = validateAndParse(schemas.UpdateCategorySchema, body);
|
|
543
601
|
if (!validation.success) return validation.response;
|
|
@@ -550,6 +608,7 @@ function createGalleryRoutes(config) {
|
|
|
550
608
|
const categoryItemDELETE = config.apiWrapper(async (ctx) => {
|
|
551
609
|
const id = getRouteId(ctx);
|
|
552
610
|
if (!id) return jsonError("missing route param: id", 400, "InvalidParams");
|
|
611
|
+
if (!canManageCategories(config, ctx)) return jsonError("forbidden", 403, "Forbidden");
|
|
553
612
|
try {
|
|
554
613
|
await categoryService.remove(id);
|
|
555
614
|
} catch (err) {
|