• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

teableio / teable / 21892749536

11 Feb 2026 04:28AM UTC coverage: 64.087% (-0.05%) from 64.133%
21892749536

push

github

web-flow
[sync] feat(observability): add OTEL metrics instrumentation and dashboards (T1991) (#1230) (#2586)

Synced from teableio/teable-ee@797b30c

Co-authored-by: teable-bot <bot@teable.io>

4978 of 6515 branches covered (76.41%)

1106 of 1794 new or added lines in 83 files covered. (61.65%)

46 existing lines in 11 files now uncovered.

22942 of 35798 relevant lines covered (64.09%)

9133.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/apps/nestjs-backend/src/features/base-node/base-node.controller.ts
1
/* eslint-disable sonarjs/no-duplicate-string */
2
import { Body, Controller, Delete, Get, Param, Post, Put, UseGuards } from '@nestjs/common';
3
import type { IBaseNodeTreeVo, IBaseNodeVo, IDeleteBaseNodeVo } from '@teable/openapi';
4
import {
5
  moveBaseNodeRoSchema,
6
  createBaseNodeRoSchema,
7
  duplicateBaseNodeRoSchema,
8
  ICreateBaseNodeRo,
9
  IDuplicateBaseNodeRo,
10
  IMoveBaseNodeRo,
11
  updateBaseNodeRoSchema,
12
  IUpdateBaseNodeRo,
13
} from '@teable/openapi';
14
import { ClsService } from 'nestjs-cls';
15
import { EmitControllerEvent } from '../../event-emitter/decorators/emit-controller-event.decorator';
16
import { Events } from '../../event-emitter/events';
17
import type { IClsStore } from '../../types/cls';
18
import { ZodValidationPipe } from '../../zod.validation.pipe';
19
import { AllowAnonymous } from '../auth/decorators/allow-anonymous.decorator';
20
import { BaseNodePermissions } from '../auth/decorators/base-node-permissions.decorator';
21
import { Permissions } from '../auth/decorators/permissions.decorator';
22
import { BaseNodePermissionGuard } from '../auth/guard/base-node-permission.guard';
23
import { checkBaseNodePermission } from './base-node.permission.helper';
24
import { BaseNodeService } from './base-node.service';
25
import { BaseNodeAction } from './types';
26

27
@Controller('api/base/:baseId/node')
28
@UseGuards(BaseNodePermissionGuard)
29
@AllowAnonymous()
30
export class BaseNodeController {
31
  constructor(
32
    private readonly baseNodeService: BaseNodeService,
290✔
33
    private readonly cls: ClsService<IClsStore>
290✔
34
  ) {}
35

36
  @Get('list')
37
  @Permissions('base|read')
38
  async getList(@Param('baseId') baseId: string): Promise<IBaseNodeVo[]> {
39
    const permissionContext = await this.getPermissionContext(baseId);
6✔
40
    const nodeList = await this.baseNodeService.getList(baseId);
6✔
41
    return nodeList.filter((node) =>
22✔
42
      checkBaseNodePermission(
43
        { resourceType: node.resourceType, resourceId: node.resourceId },
44
        BaseNodeAction.Read,
45
        permissionContext
46
      )
47
    );
48
  }
49

50
  @Get('tree')
51
  @Permissions('base|read')
52
  async getTree(@Param('baseId') baseId: string): Promise<IBaseNodeTreeVo> {
53
    const permissionContext = await this.getPermissionContext(baseId);
42✔
54
    const tree = await this.baseNodeService.getTree(baseId);
42✔
55
    return {
42✔
56
      ...tree,
57
      nodes: tree.nodes.filter((node) =>
150✔
58
        checkBaseNodePermission(
59
          { resourceType: node.resourceType, resourceId: node.resourceId },
60
          BaseNodeAction.Read,
61
          permissionContext
62
        )
63
      ),
64
    };
65
  }
66

67
  @Get(':nodeId')
68
  @Permissions('base|read')
69
  @BaseNodePermissions(BaseNodeAction.Read)
70
  async getNode(
71
    @Param('baseId') baseId: string,
72
    @Param('nodeId') nodeId: string
73
  ): Promise<IBaseNodeVo> {
74
    return this.baseNodeService.getNodeVo(baseId, nodeId);
16✔
75
  }
76

77
  @Post()
78
  @Permissions('base|read')
79
  @BaseNodePermissions(BaseNodeAction.Create)
80
  @EmitControllerEvent(Events.BASE_NODE_CREATE)
81
  async create(
82
    @Param('baseId') baseId: string,
83
    @Body(new ZodValidationPipe(createBaseNodeRoSchema)) ro: ICreateBaseNodeRo
84
  ): Promise<IBaseNodeVo> {
85
    return this.baseNodeService.create(baseId, ro);
238✔
86
  }
87

88
  @Post(':nodeId/duplicate')
89
  @Permissions('base|read')
90
  @BaseNodePermissions(BaseNodeAction.Read, BaseNodeAction.Create)
91
  @EmitControllerEvent(Events.BASE_NODE_CREATE)
92
  async duplicate(
93
    @Param('baseId') baseId: string,
94
    @Param('nodeId') nodeId: string,
95
    @Body(new ZodValidationPipe(duplicateBaseNodeRoSchema)) ro: IDuplicateBaseNodeRo
96
  ): Promise<IBaseNodeVo> {
97
    return this.baseNodeService.duplicate(baseId, nodeId, ro);
10✔
98
  }
99

100
  @Put(':nodeId')
101
  @Permissions('base|read')
102
  @BaseNodePermissions(BaseNodeAction.Update)
103
  @EmitControllerEvent(Events.BASE_NODE_UPDATE)
104
  async update(
105
    @Param('baseId') baseId: string,
106
    @Param('nodeId') nodeId: string,
107
    @Body(new ZodValidationPipe(updateBaseNodeRoSchema)) ro: IUpdateBaseNodeRo
108
  ): Promise<IBaseNodeVo> {
109
    return this.baseNodeService.update(baseId, nodeId, ro);
14✔
110
  }
111

112
  @Put(':nodeId/move')
113
  @Permissions('base|update')
114
  async move(
115
    @Param('baseId') baseId: string,
116
    @Param('nodeId') nodeId: string,
117
    @Body(new ZodValidationPipe(moveBaseNodeRoSchema)) ro: IMoveBaseNodeRo
118
  ): Promise<IBaseNodeVo> {
119
    return this.baseNodeService.move(baseId, nodeId, ro);
48✔
120
  }
121

122
  @Delete(':nodeId')
123
  @Permissions('base|read')
124
  @BaseNodePermissions(BaseNodeAction.Delete)
125
  @EmitControllerEvent(Events.BASE_NODE_DELETE)
126
  async delete(
127
    @Param('baseId') baseId: string,
128
    @Param('nodeId') nodeId: string
129
  ): Promise<IDeleteBaseNodeVo> {
130
    return this.baseNodeService.delete(baseId, nodeId);
198✔
131
  }
132

133
  @Delete(':nodeId/permanent')
134
  @Permissions('base|read')
135
  @BaseNodePermissions(BaseNodeAction.Delete)
136
  @EmitControllerEvent(Events.BASE_NODE_DELETE)
137
  async permanentDelete(
138
    @Param('baseId') baseId: string,
139
    @Param('nodeId') nodeId: string
140
  ): Promise<IDeleteBaseNodeVo> {
NEW
141
    const result = await this.baseNodeService.delete(baseId, nodeId, true);
×
NEW
142
    return { ...result, permanent: true };
×
143
  }
144

145
  protected async getPermissionContext(_baseId: string) {
146
    const permissions = this.cls.get('permissions');
48✔
147
    const permissionSet = new Set(permissions);
48✔
148
    return { permissionSet };
48✔
149
  }
150
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc