1import { Inject, Body, Controller, Delete, Get, Param, Post, Req } from "@nestjs/common";
2import type { Request } from "express";
3import { z } from "zod";
4import { ShareService } from "./share.service.js";
5import { ZodValidate } from "../../common/pipes/zod-validation.pipe.js";
6import { requireActor } from "../../common/types.js";
7import { ApiError } from "../../common/errors.js";
8
9const CreateShareDto = z.object({
10 workspaceId: z.string().min(1),
11 targetType: z.enum(["page", "database"]),
12 targetId: z.string().min(1),
13 kind: z.enum(["link", "public", "invite"]).default("link"),
14 level: z.enum(["VIEW", "COMMENT", "EDIT"]).default("VIEW"),
15 email: z.string().email().optional(),
16 expiresAt: z.string().datetime({ offset: true }).optional()
17});
18type CreateShareInput = z.infer<typeof CreateShareDto>;
19
20@Controller()
21export class ShareController {
22 constructor(@Inject(ShareService) private readonly shares: ShareService) {}
23
24 @Post("shares")
25 create(
26 @Body(ZodValidate(CreateShareDto)) body: CreateShareInput,
27 @Req() req: Request
28 ) {
29 return this.shares.create(requireActor(req), body, req);
30 }
31
32 @Get("shares/:workspaceId")
33 list(@Param("workspaceId") workspaceId: string, @Req() req: Request) {
34 return this.shares.list(workspaceId, requireActor(req));
35 }
36
37 @Delete("shares/:id")
38 remove(@Param("id") id: string, @Req() req: Request) {
39 return this.shares.remove(id, requireActor(req), req);
40 }
41
42
46 @Get("share/:slug")
47 async publicGet(@Param("slug") slug: string) {
48 const result = await this.shares.publicGet(slug);
49 if (!result) throw ApiError.notFound("Share not found.");
50 return result;
51 }
52}
53