@dismissible/nestjs-dismissible 0.0.2-canary.738340d.0
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.
- package/README.md +506 -0
- package/jest.config.ts +29 -0
- package/package.json +63 -0
- package/project.json +42 -0
- package/src/api/dismissible-item-response.dto.ts +38 -0
- package/src/api/dismissible-item.mapper.spec.ts +63 -0
- package/src/api/dismissible-item.mapper.ts +33 -0
- package/src/api/index.ts +7 -0
- package/src/api/use-cases/api-tags.constants.ts +4 -0
- package/src/api/use-cases/dismiss/dismiss.controller.spec.ts +42 -0
- package/src/api/use-cases/dismiss/dismiss.controller.ts +63 -0
- package/src/api/use-cases/dismiss/dismiss.response.dto.ts +7 -0
- package/src/api/use-cases/dismiss/index.ts +2 -0
- package/src/api/use-cases/get-or-create/get-or-create.controller.spec.ts +76 -0
- package/src/api/use-cases/get-or-create/get-or-create.controller.ts +106 -0
- package/src/api/use-cases/get-or-create/get-or-create.request.dto.ts +17 -0
- package/src/api/use-cases/get-or-create/get-or-create.response.dto.ts +7 -0
- package/src/api/use-cases/get-or-create/index.ts +3 -0
- package/src/api/use-cases/index.ts +3 -0
- package/src/api/use-cases/restore/index.ts +2 -0
- package/src/api/use-cases/restore/restore.controller.spec.ts +42 -0
- package/src/api/use-cases/restore/restore.controller.ts +63 -0
- package/src/api/use-cases/restore/restore.response.dto.ts +7 -0
- package/src/core/create-options.ts +9 -0
- package/src/core/dismissible-core.service.spec.ts +357 -0
- package/src/core/dismissible-core.service.ts +161 -0
- package/src/core/dismissible.service.spec.ts +144 -0
- package/src/core/dismissible.service.ts +188 -0
- package/src/core/hook-runner.service.spec.ts +304 -0
- package/src/core/hook-runner.service.ts +267 -0
- package/src/core/index.ts +6 -0
- package/src/core/lifecycle-hook.interface.ts +122 -0
- package/src/core/service-responses.interface.ts +34 -0
- package/src/dismissible.module.ts +83 -0
- package/src/events/dismissible.events.ts +105 -0
- package/src/events/events.constants.ts +21 -0
- package/src/events/index.ts +2 -0
- package/src/exceptions/dismissible.exceptions.spec.ts +50 -0
- package/src/exceptions/dismissible.exceptions.ts +69 -0
- package/src/exceptions/index.ts +1 -0
- package/src/index.ts +8 -0
- package/src/request/index.ts +2 -0
- package/src/request/request-context.decorator.ts +14 -0
- package/src/request/request-context.interface.ts +6 -0
- package/src/response/dtos/base-response.dto.ts +11 -0
- package/src/response/dtos/error-response.dto.ts +36 -0
- package/src/response/dtos/index.ts +3 -0
- package/src/response/dtos/success-response.dto.ts +34 -0
- package/src/response/http-exception-filter.ts +21 -0
- package/src/response/index.ts +4 -0
- package/src/response/response.module.ts +9 -0
- package/src/response/response.service.spec.ts +86 -0
- package/src/response/response.service.ts +20 -0
- package/src/testing/factories.ts +45 -0
- package/src/testing/index.ts +1 -0
- package/src/utils/date/date.service.spec.ts +104 -0
- package/src/utils/date/date.service.ts +19 -0
- package/src/utils/date/index.ts +1 -0
- package/src/utils/dismissible.helper.ts +9 -0
- package/src/utils/index.ts +3 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lib.json +14 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { HttpException, HttpStatus } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Error response structure for dismissible exceptions.
|
|
5
|
+
*/
|
|
6
|
+
interface IDismissibleErrorResponse {
|
|
7
|
+
statusCode: number;
|
|
8
|
+
error: string;
|
|
9
|
+
code: string;
|
|
10
|
+
message: string;
|
|
11
|
+
itemId?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Base exception class for dismissible errors.
|
|
16
|
+
*/
|
|
17
|
+
abstract class DismissibleException extends HttpException {
|
|
18
|
+
constructor(message: string, code: string, statusCode: HttpStatus, itemId?: string) {
|
|
19
|
+
const response: IDismissibleErrorResponse = {
|
|
20
|
+
statusCode,
|
|
21
|
+
error: HttpStatus[statusCode].replace(/_/g, ' '),
|
|
22
|
+
code,
|
|
23
|
+
message,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
if (itemId) {
|
|
27
|
+
response.itemId = itemId;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
super(response, statusCode);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Exception thrown when an item is not found.
|
|
36
|
+
*/
|
|
37
|
+
export class ItemNotFoundException extends DismissibleException {
|
|
38
|
+
constructor(itemId: string) {
|
|
39
|
+
super(`Item with id "${itemId}" not found`, 'ITEM_NOT_FOUND', HttpStatus.BAD_REQUEST, itemId);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Exception thrown when trying to dismiss an already dismissed item.
|
|
45
|
+
*/
|
|
46
|
+
export class ItemAlreadyDismissedException extends DismissibleException {
|
|
47
|
+
constructor(itemId: string) {
|
|
48
|
+
super(
|
|
49
|
+
`Item with id "${itemId}" is already dismissed`,
|
|
50
|
+
'ITEM_ALREADY_DISMISSED',
|
|
51
|
+
HttpStatus.BAD_REQUEST,
|
|
52
|
+
itemId,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Exception thrown when trying to restore an item that is not dismissed.
|
|
59
|
+
*/
|
|
60
|
+
export class ItemNotDismissedException extends DismissibleException {
|
|
61
|
+
constructor(itemId: string) {
|
|
62
|
+
super(
|
|
63
|
+
`Item with id "${itemId}" is not dismissed`,
|
|
64
|
+
'ITEM_NOT_DISMISSED',
|
|
65
|
+
HttpStatus.BAD_REQUEST,
|
|
66
|
+
itemId,
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dismissible.exceptions';
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { IRequestContext } from './request-context.interface';
|
|
4
|
+
|
|
5
|
+
export const RequestContext = createParamDecorator(
|
|
6
|
+
(_data: unknown, ctx: ExecutionContext): IRequestContext => {
|
|
7
|
+
const request = ctx.switchToHttp().getRequest();
|
|
8
|
+
const headers = request.headers;
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
requestId: headers['x-request-id'] ?? uuidv4(),
|
|
12
|
+
};
|
|
13
|
+
},
|
|
14
|
+
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ApiProperty } from '@nestjs/swagger';
|
|
2
|
+
|
|
3
|
+
export type IErrorResponseDto = {
|
|
4
|
+
error: {
|
|
5
|
+
message: string;
|
|
6
|
+
code: number;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* DTO representing error details in API responses
|
|
12
|
+
*/
|
|
13
|
+
export class ErrorDetailsDto {
|
|
14
|
+
@ApiProperty({
|
|
15
|
+
description: 'Error message',
|
|
16
|
+
example: 'Item not found',
|
|
17
|
+
})
|
|
18
|
+
message: string;
|
|
19
|
+
|
|
20
|
+
@ApiProperty({
|
|
21
|
+
description: 'HTTP status code',
|
|
22
|
+
example: 404,
|
|
23
|
+
})
|
|
24
|
+
code: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* DTO for error responses
|
|
29
|
+
*/
|
|
30
|
+
export class ErrorResponseDto implements IErrorResponseDto {
|
|
31
|
+
@ApiProperty({
|
|
32
|
+
description: 'Error details',
|
|
33
|
+
type: ErrorDetailsDto,
|
|
34
|
+
})
|
|
35
|
+
error: ErrorDetailsDto;
|
|
36
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Type } from '@nestjs/common';
|
|
2
|
+
import { ApiProperty } from '@nestjs/swagger';
|
|
3
|
+
|
|
4
|
+
export type ISuccessResponseDto<T> = {
|
|
5
|
+
data: T;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Factory function to create a success response DTO wrapper.
|
|
10
|
+
*
|
|
11
|
+
* This allows wrapping any data class in a consistent `{ data: T }` structure
|
|
12
|
+
* with proper Swagger documentation.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* class UserDto {
|
|
17
|
+
* @ApiProperty()
|
|
18
|
+
* id: string;
|
|
19
|
+
*
|
|
20
|
+
* @ApiProperty()
|
|
21
|
+
* name: string;
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* export class GetUserResponseDto extends SuccessResponseDto(UserDto) {}
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function SuccessResponseDto<T extends Type>(dataClass: T) {
|
|
28
|
+
class SuccessResponse implements ISuccessResponseDto<T> {
|
|
29
|
+
@ApiProperty({ type: dataClass })
|
|
30
|
+
data!: InstanceType<T>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return SuccessResponse;
|
|
34
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { IErrorResponseDto } from './dtos';
|
|
4
|
+
|
|
5
|
+
@Catch(HttpException)
|
|
6
|
+
export class HttpExceptionFilter implements ExceptionFilter {
|
|
7
|
+
catch(exception: HttpException, host: ArgumentsHost) {
|
|
8
|
+
const ctx = host.switchToHttp();
|
|
9
|
+
const response = ctx.getResponse<Response>();
|
|
10
|
+
const status = exception.getStatus();
|
|
11
|
+
|
|
12
|
+
const errorResponse: IErrorResponseDto = {
|
|
13
|
+
error: {
|
|
14
|
+
message: exception.message,
|
|
15
|
+
code: status,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
response.status(status).json(errorResponse);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { ResponseService } from './response.service';
|
|
2
|
+
import { NotFoundException } from '@nestjs/common';
|
|
3
|
+
|
|
4
|
+
describe('ResponseService', () => {
|
|
5
|
+
let service: ResponseService;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
// Manually create the service with no dependencies
|
|
9
|
+
service = new ResponseService();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
describe('success', () => {
|
|
13
|
+
it('should return a success response with the provided data', () => {
|
|
14
|
+
// Arrange
|
|
15
|
+
const testData = { id: '123', name: 'Test Item' };
|
|
16
|
+
|
|
17
|
+
// Act
|
|
18
|
+
const result = service.success(testData);
|
|
19
|
+
|
|
20
|
+
// Assert
|
|
21
|
+
expect(result).toEqual({
|
|
22
|
+
data: testData,
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should work with primitive data types', () => {
|
|
27
|
+
// Arrange
|
|
28
|
+
const testString = 'Test String';
|
|
29
|
+
|
|
30
|
+
// Act
|
|
31
|
+
const result = service.success(testString);
|
|
32
|
+
|
|
33
|
+
// Assert
|
|
34
|
+
expect(result).toEqual({
|
|
35
|
+
data: testString,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should work with array data', () => {
|
|
40
|
+
// Arrange
|
|
41
|
+
const testArray = [1, 2, 3];
|
|
42
|
+
|
|
43
|
+
// Act
|
|
44
|
+
const result = service.success(testArray);
|
|
45
|
+
|
|
46
|
+
// Assert
|
|
47
|
+
expect(result).toEqual({
|
|
48
|
+
data: testArray,
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should handle null data', () => {
|
|
53
|
+
// Act
|
|
54
|
+
const result = service.success(null);
|
|
55
|
+
|
|
56
|
+
// Assert
|
|
57
|
+
expect(result).toEqual({
|
|
58
|
+
data: null,
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should handle undefined data', () => {
|
|
63
|
+
// Act
|
|
64
|
+
const result = service.success(undefined);
|
|
65
|
+
|
|
66
|
+
// Assert
|
|
67
|
+
expect(result).toEqual({
|
|
68
|
+
data: undefined,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('error', () => {
|
|
74
|
+
it('should return an error response with the provided message', () => {
|
|
75
|
+
const errorMessage = new NotFoundException('Not found');
|
|
76
|
+
const result = service.error(errorMessage);
|
|
77
|
+
|
|
78
|
+
expect(result).toEqual({
|
|
79
|
+
error: {
|
|
80
|
+
message: 'Not found',
|
|
81
|
+
code: 404,
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { HttpException, Injectable } from '@nestjs/common';
|
|
2
|
+
import { IErrorResponseDto, ISuccessResponseDto } from './dtos';
|
|
3
|
+
|
|
4
|
+
@Injectable()
|
|
5
|
+
export class ResponseService {
|
|
6
|
+
success<T>(data: T): ISuccessResponseDto<T> {
|
|
7
|
+
return {
|
|
8
|
+
data,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
error(error: HttpException): IErrorResponseDto {
|
|
13
|
+
return {
|
|
14
|
+
error: {
|
|
15
|
+
message: error.message,
|
|
16
|
+
code: error.getStatus(),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BaseMetadata, DismissibleItemDto } from '@dismissible/nestjs-dismissible-item';
|
|
2
|
+
import { DismissibleItemFactory } from '@dismissible/nestjs-dismissible-item';
|
|
3
|
+
import { IRequestContext } from '../request/request-context.interface';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shared factory instance for test helpers.
|
|
7
|
+
*/
|
|
8
|
+
const testItemFactory = new DismissibleItemFactory();
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a test dismissible item.
|
|
12
|
+
*/
|
|
13
|
+
export function createTestItem<TMetadata extends BaseMetadata = BaseMetadata>(
|
|
14
|
+
overrides: Partial<DismissibleItemDto<TMetadata>> = {},
|
|
15
|
+
): DismissibleItemDto<TMetadata> {
|
|
16
|
+
return testItemFactory.create({
|
|
17
|
+
id: overrides.id ?? 'test-item-id',
|
|
18
|
+
createdAt: overrides.createdAt ?? new Date('2024-01-15T10:00:00.000Z'),
|
|
19
|
+
userId: overrides.userId ?? 'test-user-id',
|
|
20
|
+
metadata: overrides.metadata,
|
|
21
|
+
dismissedAt: overrides.dismissedAt,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Create a test request context.
|
|
27
|
+
*/
|
|
28
|
+
export function createTestContext(overrides: Partial<IRequestContext> = {}): IRequestContext {
|
|
29
|
+
return {
|
|
30
|
+
requestId: 'test-request-id',
|
|
31
|
+
...overrides,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Create a dismissed test item.
|
|
37
|
+
*/
|
|
38
|
+
export function createDismissedTestItem<TMetadata extends BaseMetadata = BaseMetadata>(
|
|
39
|
+
overrides: Partial<DismissibleItemDto<TMetadata>> = {},
|
|
40
|
+
): DismissibleItemDto<TMetadata> {
|
|
41
|
+
return createTestItem({
|
|
42
|
+
dismissedAt: new Date('2024-01-15T12:00:00.000Z'),
|
|
43
|
+
...overrides,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './factories';
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { DateService } from './date.service';
|
|
2
|
+
|
|
3
|
+
describe('DateService', () => {
|
|
4
|
+
let service: DateService;
|
|
5
|
+
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
service = new DateService();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe('getNow', () => {
|
|
11
|
+
it('should return current date', () => {
|
|
12
|
+
const before = new Date();
|
|
13
|
+
const result = service.getNow();
|
|
14
|
+
const after = new Date();
|
|
15
|
+
|
|
16
|
+
expect(result).toBeInstanceOf(Date);
|
|
17
|
+
expect(result.getTime()).toBeGreaterThanOrEqual(before.getTime());
|
|
18
|
+
expect(result.getTime()).toBeLessThanOrEqual(after.getTime());
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should return a new date instance each time', () => {
|
|
22
|
+
const date1 = service.getNow();
|
|
23
|
+
const date2 = service.getNow();
|
|
24
|
+
|
|
25
|
+
expect(date1).not.toBe(date2);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('parseIso', () => {
|
|
30
|
+
it('should parse ISO 8601 string to Date', () => {
|
|
31
|
+
const isoString = '2024-01-15T10:30:00.000Z';
|
|
32
|
+
const result = service.parseIso(isoString);
|
|
33
|
+
|
|
34
|
+
expect(result).toBeInstanceOf(Date);
|
|
35
|
+
expect(result.toISOString()).toBe(isoString);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should parse date-only ISO string', () => {
|
|
39
|
+
const isoString = '2024-01-15';
|
|
40
|
+
const result = service.parseIso(isoString);
|
|
41
|
+
|
|
42
|
+
expect(result).toBeInstanceOf(Date);
|
|
43
|
+
expect(result.getFullYear()).toBe(2024);
|
|
44
|
+
expect(result.getMonth()).toBe(0); // January is 0
|
|
45
|
+
expect(result.getDate()).toBe(15);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should parse ISO string with timezone offset', () => {
|
|
49
|
+
const isoString = '2024-01-15T10:30:00+05:00';
|
|
50
|
+
const result = service.parseIso(isoString);
|
|
51
|
+
|
|
52
|
+
expect(result).toBeInstanceOf(Date);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should handle various ISO formats', () => {
|
|
56
|
+
const testCases = ['2024-01-15T10:30:00.000Z', '2024-01-15T10:30:00Z', '2024-01-15'];
|
|
57
|
+
|
|
58
|
+
testCases.forEach((isoString) => {
|
|
59
|
+
const result = service.parseIso(isoString);
|
|
60
|
+
expect(result).toBeInstanceOf(Date);
|
|
61
|
+
expect(isNaN(result.getTime())).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe('toIso', () => {
|
|
67
|
+
it('should convert Date to ISO 8601 string', () => {
|
|
68
|
+
const date = new Date('2024-01-15T10:30:00.000Z');
|
|
69
|
+
const result = service.toIso(date);
|
|
70
|
+
|
|
71
|
+
expect(result).toBe('2024-01-15T10:30:00.000Z');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should produce valid ISO string format', () => {
|
|
75
|
+
const date = new Date('2024-12-25T23:59:59.999Z');
|
|
76
|
+
const result = service.toIso(date);
|
|
77
|
+
|
|
78
|
+
expect(result).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/);
|
|
79
|
+
expect(result).toBe('2024-12-25T23:59:59.999Z');
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should handle dates at start of epoch', () => {
|
|
83
|
+
const date = new Date('1970-01-01T00:00:00.000Z');
|
|
84
|
+
const result = service.toIso(date);
|
|
85
|
+
|
|
86
|
+
expect(result).toBe('1970-01-01T00:00:00.000Z');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should handle dates in the future', () => {
|
|
90
|
+
const date = new Date('2099-12-31T23:59:59.999Z');
|
|
91
|
+
const result = service.toIso(date);
|
|
92
|
+
|
|
93
|
+
expect(result).toBe('2099-12-31T23:59:59.999Z');
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('should round-trip through parseIso and toIso', () => {
|
|
97
|
+
const originalIso = '2024-01-15T10:30:00.000Z';
|
|
98
|
+
const date = service.parseIso(originalIso);
|
|
99
|
+
const result = service.toIso(date);
|
|
100
|
+
|
|
101
|
+
expect(result).toBe(originalIso);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Service for date operations.
|
|
5
|
+
*/
|
|
6
|
+
@Injectable()
|
|
7
|
+
export class DateService {
|
|
8
|
+
getNow(): Date {
|
|
9
|
+
return new Date();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
parseIso(isoString: string): Date {
|
|
13
|
+
return new Date(isoString);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
toIso(date: Date): string {
|
|
17
|
+
return date.toISOString();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './date.service';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { BaseMetadata, DismissibleItemDto } from '@dismissible/nestjs-dismissible-item';
|
|
3
|
+
|
|
4
|
+
@Injectable()
|
|
5
|
+
export class DismissibleHelper {
|
|
6
|
+
isDismissed<TMetadata extends BaseMetadata>(item: DismissibleItemDto<TMetadata>): boolean {
|
|
7
|
+
return item.dismissedAt !== undefined && item.dismissedAt !== null;
|
|
8
|
+
}
|
|
9
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../dist/out-tsc",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"module": "commonjs",
|
|
7
|
+
"types": ["node", "jest"],
|
|
8
|
+
"emitDecoratorMetadata": true,
|
|
9
|
+
"experimentalDecorators": true,
|
|
10
|
+
"target": "ES2021"
|
|
11
|
+
},
|
|
12
|
+
"exclude": ["node_modules"],
|
|
13
|
+
"include": ["src/**/*.ts"]
|
|
14
|
+
}
|