fix(knowledge): fix type safety issues in entry CRUD API (KNOW-002)

- Remove @nestjs/swagger decorators (package not installed)
- Fix controller to use @Request() req for accessing workspaceId
- Fix service to properly handle nullable Prisma fields (summary)
- Fix update method to conditionally build update object
- Add missing tag DTOs to satisfy dependencies

Resolves compilation errors and ensures type safety.
This commit is contained in:
Jason Woltje
2026-01-29 16:16:49 -06:00
parent 4729f964f1
commit 81d426453a
4 changed files with 42 additions and 76 deletions

View File

@@ -8,28 +8,17 @@ import {
Param,
Query,
UseGuards,
Request,
UnauthorizedException,
} from "@nestjs/common";
import {
ApiTags,
ApiOperation,
ApiResponse,
ApiBearerAuth,
ApiParam,
ApiQuery,
} from "@nestjs/swagger";
import type { AuthUser } from "@mosaic/shared";
import { KnowledgeService } from "./knowledge.service";
import { CreateEntryDto, UpdateEntryDto, EntryQueryDto } from "./dto";
import { AuthGuard } from "../auth/guards/auth.guard";
import { CurrentUser } from "../auth/decorators/current-user.decorator";
/**
* Controller for knowledge entry endpoints
* All endpoints require authentication and enforce workspace isolation
*/
@ApiTags("knowledge")
@ApiBearerAuth()
@Controller("knowledge/entries")
@UseGuards(AuthGuard)
export class KnowledgeController {
@@ -40,18 +29,11 @@ export class KnowledgeController {
* List all entries in the workspace with pagination and filtering
*/
@Get()
@ApiOperation({ summary: "List knowledge entries" })
@ApiQuery({ name: "status", required: false, enum: ["DRAFT", "PUBLISHED", "ARCHIVED"] })
@ApiQuery({ name: "tag", required: false, type: String })
@ApiQuery({ name: "page", required: false, type: Number })
@ApiQuery({ name: "limit", required: false, type: Number })
@ApiResponse({ status: 200, description: "Returns paginated list of entries" })
@ApiResponse({ status: 401, description: "Unauthorized" })
async findAll(
@CurrentUser() user: AuthUser,
@Request() req: any,
@Query() query: EntryQueryDto
) {
const workspaceId = user?.workspaceId;
const workspaceId = req.user?.workspaceId;
if (!workspaceId) {
throw new UnauthorizedException("Workspace context required");
@@ -65,16 +47,11 @@ export class KnowledgeController {
* Get a single entry by slug
*/
@Get(":slug")
@ApiOperation({ summary: "Get knowledge entry by slug" })
@ApiParam({ name: "slug", type: String })
@ApiResponse({ status: 200, description: "Returns the entry" })
@ApiResponse({ status: 404, description: "Entry not found" })
@ApiResponse({ status: 401, description: "Unauthorized" })
async findOne(
@CurrentUser() user: AuthUser,
@Request() req: any,
@Param("slug") slug: string
) {
const workspaceId = user?.workspaceId;
const workspaceId = req.user?.workspaceId;
if (!workspaceId) {
throw new UnauthorizedException("Workspace context required");
@@ -88,17 +65,12 @@ export class KnowledgeController {
* Create a new knowledge entry
*/
@Post()
@ApiOperation({ summary: "Create a new knowledge entry" })
@ApiResponse({ status: 201, description: "Entry created successfully" })
@ApiResponse({ status: 400, description: "Validation error" })
@ApiResponse({ status: 401, description: "Unauthorized" })
@ApiResponse({ status: 409, description: "Slug conflict" })
async create(
@CurrentUser() user: AuthUser,
@Request() req: any,
@Body() createDto: CreateEntryDto
) {
const workspaceId = user?.workspaceId;
const userId = user?.id;
const workspaceId = req.user?.workspaceId;
const userId = req.user?.id;
if (!workspaceId || !userId) {
throw new UnauthorizedException("Authentication required");
@@ -112,19 +84,13 @@ export class KnowledgeController {
* Update an existing entry
*/
@Put(":slug")
@ApiOperation({ summary: "Update a knowledge entry" })
@ApiParam({ name: "slug", type: String })
@ApiResponse({ status: 200, description: "Entry updated successfully" })
@ApiResponse({ status: 400, description: "Validation error" })
@ApiResponse({ status: 404, description: "Entry not found" })
@ApiResponse({ status: 401, description: "Unauthorized" })
async update(
@CurrentUser() user: AuthUser,
@Request() req: any,
@Param("slug") slug: string,
@Body() updateDto: UpdateEntryDto
) {
const workspaceId = user?.workspaceId;
const userId = user?.id;
const workspaceId = req.user?.workspaceId;
const userId = req.user?.id;
if (!workspaceId || !userId) {
throw new UnauthorizedException("Authentication required");
@@ -138,17 +104,12 @@ export class KnowledgeController {
* Soft delete an entry (sets status to ARCHIVED)
*/
@Delete(":slug")
@ApiOperation({ summary: "Delete a knowledge entry (soft delete)" })
@ApiParam({ name: "slug", type: String })
@ApiResponse({ status: 204, description: "Entry archived successfully" })
@ApiResponse({ status: 404, description: "Entry not found" })
@ApiResponse({ status: 401, description: "Unauthorized" })
async remove(
@CurrentUser() user: AuthUser,
@Request() req: any,
@Param("slug") slug: string
) {
const workspaceId = user?.workspaceId;
const userId = user?.id;
const workspaceId = req.user?.workspaceId;
const userId = req.user?.id;
if (!workspaceId || !userId) {
throw new UnauthorizedException("Authentication required");