@viplance/nestjs-logger 0.3.8 → 0.4.1

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.
Files changed (45) hide show
  1. package/README.md +37 -4
  2. package/dist/defaults.js +1 -1
  3. package/dist/entities/log.entity.d.ts +2 -2
  4. package/dist/entities/log.entity.js +1 -1
  5. package/dist/guards/access.guard.d.ts +1 -1
  6. package/dist/guards/access.guard.js +2 -2
  7. package/dist/index.d.ts +4 -4
  8. package/dist/interceptors/log.interceptor.d.ts +4 -4
  9. package/dist/log.module.d.ts +1 -1
  10. package/dist/log.module.js +33 -7
  11. package/dist/log.module.js.map +1 -1
  12. package/dist/services/log.service.d.ts +15 -9
  13. package/dist/services/log.service.js +87 -30
  14. package/dist/services/log.service.js.map +1 -1
  15. package/dist/services/memory-db.service.d.ts +1 -1
  16. package/dist/services/memory-db.service.js +5 -5
  17. package/dist/services/ws.service.d.ts +18 -0
  18. package/dist/services/ws.service.js +106 -0
  19. package/dist/services/ws.service.js.map +1 -0
  20. package/dist/types/index.d.ts +3 -3
  21. package/dist/types/options.type.d.ts +7 -0
  22. package/dist/utils/entity2table.d.ts +1 -1
  23. package/dist/utils/entity2table.js +6 -6
  24. package/package.json +9 -4
  25. package/public/index.html +7 -2
  26. package/public/scripts/common.js +74 -43
  27. package/public/scripts/details-popup.js +18 -9
  28. package/public/scripts/json-viewer.js +4 -4
  29. package/public/scripts/ws.js +83 -0
  30. package/public/styles/index.css +5 -0
  31. package/src/defaults.ts +1 -1
  32. package/src/entities/log.entity.ts +3 -3
  33. package/src/guards/access.guard.ts +5 -5
  34. package/src/index.ts +4 -4
  35. package/src/interceptors/log.interceptor.ts +5 -5
  36. package/src/log.module.ts +50 -17
  37. package/src/services/log.service.ts +118 -40
  38. package/src/services/memory-db.service.ts +9 -9
  39. package/src/services/ws.d.ts +1 -0
  40. package/src/services/ws.service.ts +110 -0
  41. package/src/types/index.ts +3 -3
  42. package/src/types/log.type.ts +5 -5
  43. package/src/types/options.type.ts +7 -0
  44. package/src/utils/entity2table.ts +8 -8
  45. package/public/json.html +0 -0
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export * from "./interceptors/log.interceptor";
2
- export * from "./log.module";
3
- export * from "./types/index";
4
- export * from "./services/log.service";
1
+ export * from './interceptors/log.interceptor';
2
+ export * from './log.module';
3
+ export * from './types/index';
4
+ export * from './services/log.service';
@@ -1,8 +1,8 @@
1
- import type { CallHandler, NestInterceptor } from "@nestjs/common";
2
- import { Inject, Injectable } from "@nestjs/common";
3
- import { Observable, tap } from "rxjs";
4
- import { LogService } from "../services/log.service";
5
- import { ExecutionContextHost } from "@nestjs/core/helpers/execution-context-host";
1
+ import type { CallHandler, NestInterceptor } from '@nestjs/common';
2
+ import { Inject, Injectable } from '@nestjs/common';
3
+ import { Observable, tap } from 'rxjs';
4
+ import { LogService } from '../services/log.service';
5
+ import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
6
6
 
7
7
  @Injectable()
8
8
  export class LogInterceptor implements NestInterceptor {
package/src/log.module.ts CHANGED
@@ -1,19 +1,26 @@
1
- import { Module, Global, HttpException } from "@nestjs/common";
2
- import { LogService } from "./services/log.service";
3
- import { MemoryDbService } from "./services/memory-db.service";
4
- import { LogInterceptor } from "./interceptors/log.interceptor";
5
- import { LogModuleOptions } from "./types";
6
- import { TypeOrmModule } from "@nestjs/typeorm";
7
- import querystring from "node:querystring";
8
- import { ApplicationConfig } from "@nestjs/core";
9
- import { join } from "node:path";
10
- import { LogAccessGuard } from "./guards/access.guard";
1
+ import { Module, Global, HttpException } from '@nestjs/common';
2
+ import { LogService } from './services/log.service';
3
+ import { MemoryDbService } from './services/memory-db.service';
4
+ import { LogInterceptor } from './interceptors/log.interceptor';
5
+ import { LogModuleOptions } from './types';
6
+ import { TypeOrmModule } from '@nestjs/typeorm';
7
+ import querystring from 'node:querystring';
8
+ import { ApplicationConfig } from '@nestjs/core';
9
+ import { join } from 'node:path';
10
+ import { LogAccessGuard } from './guards/access.guard';
11
+ import { WsService } from './services/ws.service';
11
12
 
12
13
  @Global()
13
14
  @Module({
14
15
  imports: [TypeOrmModule],
15
- providers: [ApplicationConfig, LogAccessGuard, LogService, MemoryDbService],
16
- exports: [TypeOrmModule, LogService, MemoryDbService],
16
+ providers: [
17
+ ApplicationConfig,
18
+ LogAccessGuard,
19
+ LogService,
20
+ MemoryDbService,
21
+ WsService,
22
+ ],
23
+ exports: [TypeOrmModule, LogService, MemoryDbService, WsService],
17
24
  })
18
25
  export class LogModule {
19
26
  public static async init(
@@ -23,6 +30,7 @@ export class LogModule {
23
30
  app.resolve(LogService);
24
31
 
25
32
  const logService: LogService = await app.resolve(LogService);
33
+ const wsService: WsService = await app.resolve(WsService);
26
34
  const logAccessGuard: LogAccessGuard = await app.get(LogAccessGuard);
27
35
 
28
36
  if (options) {
@@ -32,14 +40,34 @@ export class LogModule {
32
40
  app.useGlobalInterceptors(new LogInterceptor(logService)); // intercept all errors
33
41
 
34
42
  if (options?.path) {
35
- app.useStaticAssets(join(__dirname, "..", "public"), {
43
+ app.useStaticAssets(join(__dirname, '..', 'public'), {
36
44
  prefix: options.path,
37
45
  });
38
46
 
39
47
  const httpAdapter = app.getHttpAdapter();
40
48
 
49
+ // frontend settings endpoint
50
+ httpAdapter.get(
51
+ join(options.path, 'settings'),
52
+ async (req: any, res: any) => {
53
+ logAccessGuard.canActivate(req);
54
+
55
+ const result: { [key: string]: any } = {};
56
+
57
+ if (options?.websocket) {
58
+ result.websocket = {
59
+ namespace: options.websocket?.namespace,
60
+ port: options.websocket?.port,
61
+ host: options.websocket?.host || req.headers?.host.split(':')[0],
62
+ };
63
+ }
64
+
65
+ res.json(result);
66
+ }
67
+ );
68
+
41
69
  // get all logs endpoint
42
- httpAdapter.get(join(options.path, "api"), async (req: any, res: any) => {
70
+ httpAdapter.get(join(options.path, 'api'), async (req: any, res: any) => {
43
71
  logAccessGuard.canActivate(req);
44
72
 
45
73
  res.json(await logService.getAll());
@@ -47,19 +75,24 @@ export class LogModule {
47
75
 
48
76
  // delete log endpoint
49
77
  httpAdapter.delete(
50
- join(options.path, "api"),
78
+ join(options.path, 'api'),
51
79
  async (req: any, res: any) => {
52
80
  logAccessGuard.canActivate(req);
53
81
 
54
- const params = querystring.parse(req.url.split("?")[1]);
82
+ const params = querystring.parse(req.url.split('?')[1]);
55
83
 
56
84
  if (!params.id) {
57
- throw new HttpException("id is required", 400);
85
+ throw new HttpException('id is required', 400);
58
86
  }
59
87
 
60
88
  res.json(await logService.delete(params.id.toString()));
61
89
  }
62
90
  );
91
+
92
+ // set up WebSocket connection
93
+ if (options?.websocket) {
94
+ wsService.setupConnection(options.websocket, options.key);
95
+ }
63
96
  }
64
97
 
65
98
  if (options?.database) {
@@ -1,36 +1,55 @@
1
- import { Injectable, LoggerService, Scope } from "@nestjs/common";
2
- import { MemoryDbService } from "./memory-db.service";
3
- import { defaultTable } from "../defaults";
4
- import { Context, LogModuleOptions, LogType } from "../types";
1
+ import {
2
+ Injectable,
3
+ LoggerService,
4
+ OnApplicationShutdown,
5
+ Scope,
6
+ } from '@nestjs/common';
7
+ import { MemoryDbService } from './memory-db.service';
8
+ import { defaultTable } from '../defaults';
9
+ import { Context, LogModuleOptions, LogType } from '../types';
5
10
  import {
6
11
  DataSource,
7
12
  DataSourceOptions,
8
13
  EntityManager,
9
14
  EntitySchema,
10
- } from "typeorm";
11
- import { createLogEntity } from "../entities/log.entity";
12
- import { ExecutionContextHost } from "@nestjs/core/helpers/execution-context-host";
13
- import { setInterval } from "timers";
14
- import { entity2table } from "../utils/entity2table";
15
+ } from 'typeorm';
16
+ import { createLogEntity } from '../entities/log.entity';
17
+ import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
18
+ import { setInterval } from 'timers';
19
+ import { entity2table } from '../utils/entity2table';
20
+ import { WsService } from './ws.service';
21
+ import { Subscription } from 'rxjs';
15
22
 
16
23
  @Injectable({ scope: Scope.TRANSIENT })
17
- export class LogService implements LoggerService {
24
+ export class LogService implements LoggerService, OnApplicationShutdown {
18
25
  static connection: DataSource;
19
26
  static options: LogModuleOptions;
20
- static Log: EntitySchema = createLogEntity(defaultTable, "memory");
27
+ static Log: EntitySchema = createLogEntity(defaultTable, 'memory');
21
28
  static timer: ReturnType<typeof setInterval>;
29
+ static subscription: Subscription;
22
30
 
23
31
  breadcrumbs: any[] = [];
24
32
 
25
- constructor(private readonly memoryDbService: MemoryDbService) {}
33
+ constructor(
34
+ private readonly memoryDbService: MemoryDbService,
35
+ private readonly wsService: WsService
36
+ ) {}
37
+
38
+ onApplicationShutdown() {
39
+ if (LogService.timer) {
40
+ clearInterval(LogService.timer);
41
+ }
42
+ }
26
43
 
27
44
  async connectDb(options: LogModuleOptions): Promise<DataSource> {
28
45
  LogService.Log = createLogEntity(
29
46
  options.database?.collection || options.database?.table || defaultTable,
30
- options.database?.type || "mongodb"
47
+ options.database?.type || 'mongodb'
31
48
  );
32
49
 
33
- this.setOptions(options);
50
+ if (!LogService.options) {
51
+ this.setOptions(options);
52
+ }
34
53
 
35
54
  const dataSourceOptions = {
36
55
  type: options.database?.type,
@@ -43,9 +62,7 @@ export class LogService implements LoggerService {
43
62
  LogService.connection = new DataSource(dataSourceOptions);
44
63
  await LogService.connection.initialize();
45
64
 
46
- if (dataSourceOptions.type !== "mongodb") {
47
- // LogService.idName = "id";
48
-
65
+ if (dataSourceOptions.type !== 'mongodb') {
49
66
  const queryRunner = LogService.connection.createQueryRunner();
50
67
 
51
68
  try {
@@ -70,6 +87,24 @@ export class LogService implements LoggerService {
70
87
 
71
88
  setOptions(options: LogModuleOptions) {
72
89
  LogService.options = options;
90
+
91
+ if (options.websocket && !LogService.subscription) {
92
+ LogService.subscription = this.wsService.onMessage.subscribe(
93
+ async (message) => {
94
+ switch (message.action) {
95
+ case 'getLogs':
96
+ this.wsService.sendMessage({
97
+ action: 'list',
98
+ data: await this.getAll(),
99
+ });
100
+ break;
101
+ case 'delete':
102
+ this.delete(message.data._id);
103
+ break;
104
+ }
105
+ }
106
+ );
107
+ }
73
108
  }
74
109
 
75
110
  addBreadcrumb(breadcrumb: any) {
@@ -124,22 +159,26 @@ export class LogService implements LoggerService {
124
159
  async getAll(): Promise<any[]> {
125
160
  return this.getConnection().find(LogService.Log, {
126
161
  select: [
127
- "_id",
128
- "type",
129
- "message",
130
- "count",
131
- "createdAt",
132
- "updatedAt",
133
- "context",
134
- "trace",
135
- "breadcrumbs",
162
+ '_id',
163
+ 'type',
164
+ 'message',
165
+ 'count',
166
+ 'createdAt',
167
+ 'updatedAt',
168
+ 'context',
169
+ 'trace',
170
+ 'breadcrumbs',
136
171
  ],
137
- order: { updatedAt: "DESC" },
172
+ order: { updatedAt: 'DESC' },
138
173
  });
139
174
  }
140
175
 
141
- async delete(id: string) {
142
- return this.getConnection().delete(LogService.Log, id);
176
+ async delete(_id: string) {
177
+ this.wsService.sendMessage({
178
+ action: 'delete',
179
+ data: { _id },
180
+ });
181
+ return this.getConnection().delete(LogService.Log, _id);
143
182
  }
144
183
 
145
184
  private async smartInsert(data: {
@@ -153,26 +192,45 @@ export class LogService implements LoggerService {
153
192
  const connection = this.getConnection();
154
193
 
155
194
  // find the same log in DB
156
- const log = await connection.findOne(LogService.Log, {
157
- where: {
158
- type: data.type,
159
- message: data.message,
160
- },
161
- });
195
+ let log;
196
+
197
+ if (LogService.options.join) {
198
+ log = await connection.findOne(LogService.Log, {
199
+ where: {
200
+ type: data.type,
201
+ message: data.message,
202
+ },
203
+ });
204
+ }
162
205
 
163
206
  const context = data.context ? this.parseContext(data.context) : undefined;
164
207
 
165
208
  if (log) {
166
- return await connection.update(LogService.Log, log["_id"], {
209
+ const updatedLog = {
210
+ context,
211
+ trace: data.trace,
212
+ breadcrumbs: this.breadcrumbs,
213
+ count: log.count + 1,
214
+ updatedAt: currentDate,
215
+ };
216
+
217
+ this.wsService.sendMessage({
218
+ action: 'update',
219
+ data: { ...log, ...updatedLog },
220
+ });
221
+
222
+ await connection.update(LogService.Log, log['_id'], {
167
223
  context,
168
224
  trace: data.trace,
169
225
  breadcrumbs: this.breadcrumbs,
170
226
  count: log.count + 1,
171
227
  updatedAt: currentDate,
172
228
  });
229
+
230
+ return { ...log, ...updatedLog };
173
231
  }
174
232
 
175
- return await connection.insert(LogService.Log, {
233
+ const insertedLog = {
176
234
  type: data.type,
177
235
  message: data.message,
178
236
  context,
@@ -181,7 +239,27 @@ export class LogService implements LoggerService {
181
239
  count: 1,
182
240
  createdAt: currentDate,
183
241
  updatedAt: currentDate,
242
+ };
243
+
244
+ const res = await connection.insert(LogService.Log, insertedLog);
245
+ const _id = this.getNewObjectId(res);
246
+
247
+ this.wsService.sendMessage({
248
+ action: 'insert',
249
+ data: { _id, ...insertedLog },
184
250
  });
251
+
252
+ return { _id, ...insertedLog };
253
+ }
254
+
255
+ private getNewObjectId(result: any): string | number {
256
+ if (result.identifiers) {
257
+ return result.identifiers[0]._id;
258
+ }
259
+
260
+ console.log(result);
261
+
262
+ return result._id;
185
263
  }
186
264
 
187
265
  private getConnection(): EntityManager {
@@ -225,9 +303,9 @@ export class LogService implements LoggerService {
225
303
  private async checkRecords() {
226
304
  if (LogService.options?.maxSize) {
227
305
  const latest = await this.getConnection().find(LogService.Log, {
228
- order: { updatedAt: "DESC" },
306
+ order: { updatedAt: 'DESC' },
229
307
  take: LogService.options?.maxSize,
230
- select: ["_id"],
308
+ select: ['_id'],
231
309
  });
232
310
 
233
311
  const latestIds = latest.map((item) => item.id);
@@ -237,7 +315,7 @@ export class LogService implements LoggerService {
237
315
  .createQueryBuilder()
238
316
  .delete()
239
317
  .from(LogService.Log)
240
- .where("_id NOT IN (:...ids)", { ids: latestIds })
318
+ .where('_id NOT IN (:...ids)', { ids: latestIds })
241
319
  .execute();
242
320
  }
243
321
  }
@@ -1,8 +1,8 @@
1
1
  // Memory DB layer
2
- import { Injectable } from "@nestjs/common";
3
- import { createHash, randomBytes } from "crypto";
4
- import { defaultTable } from "../defaults";
5
- import { EntitySchema, FindManyOptions } from "typeorm";
2
+ import { Injectable } from '@nestjs/common';
3
+ import { createHash, randomBytes } from 'crypto';
4
+ import { defaultTable } from '../defaults';
5
+ import { EntitySchema, FindManyOptions } from 'typeorm';
6
6
 
7
7
  const tables = [defaultTable];
8
8
 
@@ -20,8 +20,8 @@ export class MemoryDbService {
20
20
  const table = this.getTableName(entity);
21
21
 
22
22
  // generate new random _id
23
- const randomData = randomBytes(24).toString("hex");
24
- const _id = createHash("sha256").update(randomData).digest("hex");
23
+ const randomData = randomBytes(24).toString('hex');
24
+ const _id = createHash('sha256').update(randomData).digest('hex');
25
25
 
26
26
  this.db[table].push({
27
27
  ...data,
@@ -39,7 +39,7 @@ export class MemoryDbService {
39
39
  const table = this.getTableName(entity);
40
40
  let index: number | null = null;
41
41
 
42
- if (typeof condition === "string") {
42
+ if (typeof condition === 'string') {
43
43
  index = this.findIndex(entity, { where: { _id: condition } });
44
44
  }
45
45
 
@@ -136,8 +136,8 @@ export class MemoryDbService {
136
136
  if (
137
137
  obj1 == null ||
138
138
  obj2 == null ||
139
- typeof obj1 !== "object" ||
140
- typeof obj2 !== "object"
139
+ typeof obj1 !== 'object' ||
140
+ typeof obj2 !== 'object'
141
141
  ) {
142
142
  return false;
143
143
  }
@@ -0,0 +1 @@
1
+ declare module 'ws';
@@ -0,0 +1,110 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import WebSocket, { WebSocketServer } from 'ws';
3
+ import { LogModuleOptions } from '../types';
4
+ import { Subject } from 'rxjs';
5
+
6
+ @Injectable()
7
+ export class WsService {
8
+ public onMessage: Subject<any> = new Subject();
9
+ private ws: WebSocket | null = null;
10
+ private connected: boolean = false;
11
+ private connectionTimeout: number = 500;
12
+ private options: LogModuleOptions['websocket'] = {
13
+ port: 8080,
14
+ host: 'localhost',
15
+ };
16
+ private key: string = '';
17
+
18
+ setupConnection(options: LogModuleOptions['websocket'], key = '') {
19
+ this.options = {
20
+ ...this.options,
21
+ ...options,
22
+ };
23
+ this.key = key;
24
+
25
+ // Set up Web Socket server
26
+ if (this.ws) {
27
+ return;
28
+ }
29
+
30
+ const wsServer = new WebSocketServer({
31
+ retryCount: 1,
32
+ reconnectInterval: 1,
33
+ handshakeTimeout: this.connectionTimeout,
34
+ port: this.options?.port,
35
+ });
36
+
37
+ console.log(
38
+ `Logs WebSocket server is listening on port ${this.options.port}`
39
+ );
40
+
41
+ wsServer.on('error', this.handleError);
42
+ wsServer.on('open', () => this.handleOpenConnection());
43
+ wsServer.on('ping', () => this.ping(this.ws));
44
+ wsServer.on('close', () => this.closeConnection(this.ws));
45
+ wsServer.on('message', this.handleMessage);
46
+ wsServer.on('connection', (connection: WebSocket) => {
47
+ this.ws = connection;
48
+ connection.onmessage = this.handleMessage;
49
+ });
50
+ }
51
+
52
+ sendMessage(message: any) {
53
+ this.ws?.send(JSON.stringify(message));
54
+ }
55
+
56
+ private handleError = () => {
57
+ const serverUrl = this.getServerUrl();
58
+ console.error(`Server ${serverUrl} is not available.`);
59
+
60
+ setTimeout(this.setupConnection, this.connectionTimeout);
61
+ };
62
+
63
+ private closeConnection = (connection: any) => {
64
+ clearTimeout(connection.pingTimeout);
65
+
66
+ if (this.connected) {
67
+ console.log('Connection has been closed by server.');
68
+ this.connected = false;
69
+ this.handleError();
70
+ }
71
+ };
72
+
73
+ private ping = (connection: any) => {
74
+ console.log('Ping remote server.');
75
+ clearTimeout(connection.pingTimeout);
76
+
77
+ connection.pingTimeout = setTimeout(() => {
78
+ connection.terminate();
79
+ }, 30000 + this.connectionTimeout);
80
+ };
81
+
82
+ private handleMessage = (message: any) => {
83
+ try {
84
+ const data = JSON.parse((message.data || message).toString());
85
+
86
+ if (this.key !== '' && data.key !== this.key) {
87
+ throw new Error('WebSocket unauthorized');
88
+ }
89
+
90
+ if (this.options)
91
+ if (data.action) {
92
+ this.onMessage.next(data);
93
+ }
94
+ } catch (err) {
95
+ console.error(err);
96
+ }
97
+ };
98
+
99
+ private getServerUrl = (): string => {
100
+ return `${this.options?.secure ? 'wss' : 'ws'}://${this.options?.host}:${
101
+ this.options?.port
102
+ }`;
103
+ };
104
+
105
+ private handleOpenConnection = async () => {
106
+ this.connected = true;
107
+ const serverUrl = this.getServerUrl();
108
+ console.log(`${serverUrl} has been connected.`);
109
+ };
110
+ }
@@ -1,3 +1,3 @@
1
- export * from "./context.type";
2
- export * from "./log.type";
3
- export * from "./options.type";
1
+ export * from './context.type';
2
+ export * from './log.type';
3
+ export * from './options.type';
@@ -1,7 +1,7 @@
1
1
  export enum LogType {
2
- LOG = "log",
3
- ERROR = "error",
4
- WARN = "warn",
5
- DEBUG = "debug",
6
- VERBOSE = "verbose",
2
+ LOG = 'log',
3
+ ERROR = 'error',
4
+ WARN = 'warn',
5
+ DEBUG = 'debug',
6
+ VERBOSE = 'verbose',
7
7
  }
@@ -3,6 +3,7 @@ import { DataSourceOptions } from "typeorm";
3
3
  export type LogModuleOptions = {
4
4
  path?: string;
5
5
  key?: string; // access key
6
+ join?: boolean; // merge the message duplicates
6
7
  maxRecords?: number; // max log records
7
8
  maxAge?: number; // in days
8
9
  maxSize?: number; // in megabytes
@@ -12,4 +13,10 @@ export type LogModuleOptions = {
12
13
  table?: string;
13
14
  collection?: string;
14
15
  };
16
+ websocket?: {
17
+ port?: number;
18
+ namespace?: string;
19
+ host?: string;
20
+ secure?: boolean;
21
+ };
15
22
  };
@@ -1,5 +1,5 @@
1
- import { EntitySchema, Table } from "typeorm";
2
- import { defaultTable } from "../defaults";
1
+ import { EntitySchema, Table } from 'typeorm';
2
+ import { defaultTable } from '../defaults';
3
3
 
4
4
  export function entity2table(entity: EntitySchema): Table {
5
5
  return new Table({
@@ -9,7 +9,7 @@ export function entity2table(entity: EntitySchema): Table {
9
9
  type: resolveColumnType(col?.type),
10
10
  isPrimary: !!col?.primary,
11
11
  isGenerated: !!col?.generated,
12
- generationStrategy: col?.generated ? "increment" : undefined,
12
+ generationStrategy: col?.generated ? 'increment' : undefined,
13
13
  isUnique: !!col?.unique,
14
14
  isNullable: !!col?.nullable,
15
15
  default: col?.default,
@@ -20,14 +20,14 @@ export function entity2table(entity: EntitySchema): Table {
20
20
  function resolveColumnType(type: any): string {
21
21
  switch (type) {
22
22
  case String:
23
- return "text";
23
+ return 'text';
24
24
  case Number:
25
- return "int";
25
+ return 'int';
26
26
  case Date:
27
- return "timestamp";
27
+ return 'timestamp';
28
28
  case Boolean:
29
- return "boolean";
29
+ return 'boolean';
30
30
  default:
31
- return "text";
31
+ return 'text';
32
32
  }
33
33
  }
package/public/json.html DELETED
File without changes