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

teableio / teable / 10160390019

30 Jul 2024 10:08AM CUT coverage: 81.98% (+64.3%) from 17.697%
10160390019

Pull #779

github

web-flow
Merge a160876c8 into 521460d76
Pull Request #779: fix: skip duplicate index

4272 of 4471 branches covered (95.55%)

28270 of 34484 relevant lines covered (81.98%)

1219.86 hits per line

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

0.0
/apps/nestjs-backend/src/bootstrap.ts
1
import 'dayjs/plugin/timezone';
×
2
import 'dayjs/plugin/utc';
×
3
import fs from 'fs';
×
4
import path from 'path';
×
5
import type { INestApplication } from '@nestjs/common';
×
6
import { ValidationPipe } from '@nestjs/common';
×
7
import { ConfigService } from '@nestjs/config';
×
8
import { NestFactory } from '@nestjs/core';
×
9
import { WsAdapter } from '@nestjs/platform-ws';
×
10
import type { OpenAPIObject } from '@nestjs/swagger';
×
11
import { SwaggerModule } from '@nestjs/swagger';
×
12
import { getOpenApiDocumentation } from '@teable/openapi';
×
13
import { json, urlencoded } from 'express';
×
14
import helmet from 'helmet';
×
15
import isPortReachable from 'is-port-reachable';
×
16
import { Logger } from 'nestjs-pino';
×
17
import type { RedocOptions } from 'nestjs-redoc';
×
18
import { RedocModule } from 'nestjs-redoc';
×
19
import { AppModule } from './app.module';
×
20
import type { IBaseConfig } from './configs/base.config';
×
21
import type { ISecurityWebConfig, IApiDocConfig } from './configs/bootstrap.config';
×
22
import { GlobalExceptionFilter } from './filter/global-exception.filter';
×
23
import otelSDK from './tracing';
×
24

×
25
// eslint-disable-next-line @typescript-eslint/no-explicit-any
×
26
declare const module: any;
×
27

×
28
const host = 'localhost';
×
29

×
30
export async function setUpAppMiddleware(app: INestApplication, configService: ConfigService) {
×
31
  app.useWebSocketAdapter(new WsAdapter(app));
×
32
  app.useGlobalFilters(new GlobalExceptionFilter(configService));
×
33
  app.useGlobalPipes(
×
34
    new ValidationPipe({ transform: true, stopAtFirstError: true, forbidUnknownValues: false })
×
35
  );
×
36
  app.use(helmet());
×
37
  app.use(json({ limit: '50mb' }));
×
38
  app.use(urlencoded({ limit: '50mb', extended: true }));
×
39

×
40
  const apiDocConfig = configService.get<IApiDocConfig>('apiDoc');
×
41
  const securityWebConfig = configService.get<ISecurityWebConfig>('security.web');
×
42
  const baseConfig = configService.get<IBaseConfig>('base');
×
43
  if (!apiDocConfig?.disabled) {
×
44
    const openApiDocumentation = await getOpenApiDocumentation({
×
45
      origin: baseConfig?.publicOrigin,
×
46
      snippet: apiDocConfig?.enabledSnippet,
×
47
    });
×
48

×
49
    const jsonString = JSON.stringify(openApiDocumentation);
×
50
    fs.writeFileSync(path.join(__dirname, '/openapi.json'), jsonString);
×
51
    SwaggerModule.setup('/docs', app, openApiDocumentation as OpenAPIObject);
×
52

×
53
    // Instead of using SwaggerModule.setup() you call this module
×
54
    const redocOptions: RedocOptions = {
×
55
      logo: {
×
56
        backgroundColor: '#F0F0F0',
×
57
        altText: 'Teable logo',
×
58
      },
×
59
    };
×
60
    await RedocModule.setup('/redocs', app, openApiDocumentation as OpenAPIObject, redocOptions);
×
61
  }
×
62

×
63
  if (securityWebConfig?.cors.enabled) {
×
64
    app.enableCors();
×
65
  }
×
66
}
×
67

×
68
export async function bootstrap() {
×
69
  otelSDK.start();
×
70

×
71
  const app = await NestFactory.create(AppModule, { bufferLogs: true });
×
72
  const configService = app.get(ConfigService);
×
73

×
74
  if (module.hot) {
×
75
    module.hot.accept();
×
76
    module.hot.dispose(() => app.close());
×
77
  }
×
78

×
79
  const logger = app.get(Logger);
×
80
  app.useLogger(logger);
×
81
  app.flushLogs();
×
82

×
83
  app.enableShutdownHooks();
×
84

×
85
  await setUpAppMiddleware(app, configService);
×
86

×
87
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
×
88
  // app.getHttpServer().on('upgrade', async function (req: any, socket: any, head: any) {
×
89
  //   if (req.url.startsWith('/_next')) {
×
90
  //     console.log('upgrade: ', req.url);
×
91
  //     const server = app.get(NextService).server;
×
92
  //     return server.getUpgradeHandler()(req, socket, head);
×
93
  //   }
×
94
  // });
×
95

×
96
  const port = await getAvailablePort(configService.get<string>('PORT') as string);
×
97
  process.env.PORT = port.toString();
×
98

×
99
  await app.listen(port);
×
100

×
101
  const now = new Date();
×
102
  const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
×
103
  logger.log(`> NODE_ENV is ${process.env.NODE_ENV}`);
×
104
  logger.log(`> Ready on http://${host}:${port}`);
×
105
  logger.log(`> System Time Zone: ${timeZone}`);
×
106
  logger.log(`> Current System Time: ${now.toString()}`);
×
107

×
108
  process.on('unhandledRejection', (reason: string, promise: Promise<unknown>) => {
×
109
    logger.error(`Unhandled Rejection at: ${promise}, reason: ${reason}`);
×
110
    throw reason;
×
111
  });
×
112

×
113
  process.on('uncaughtException', (error) => {
×
114
    logger.error(error);
×
115
  });
×
116
  return app;
×
117
}
×
118

×
119
async function getAvailablePort(dPort: number | string): Promise<number> {
×
120
  let port = Number(dPort);
×
121
  while (await isPortReachable(port, { host })) {
×
122
    console.log(`> Fail on http://${host}:${port} Trying on ${port + 1}`);
×
123
    port++;
×
124
  }
×
125
  return port;
×
126
}
×
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

© 2025 Coveralls, Inc