@dismissible/nestjs-dismissible 0.0.2-canary.8976e84.0 → 0.0.2-canary.a611bd3.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 +58 -74
- package/package.json +19 -17
- package/src/api/dismissible-item-response.dto.d.ts +9 -0
- package/src/api/dismissible-item-response.dto.js +40 -0
- package/src/api/dismissible-item-response.dto.js.map +1 -0
- package/src/api/dismissible-item.mapper.d.ts +12 -0
- package/src/api/dismissible-item.mapper.js +30 -0
- package/src/api/dismissible-item.mapper.js.map +1 -0
- package/src/api/dismissible-item.mapper.spec.d.ts +1 -0
- package/src/api/dismissible-item.mapper.spec.js +43 -0
- package/src/api/dismissible-item.mapper.spec.js.map +1 -0
- package/src/api/{index.ts → index.d.ts} +1 -4
- package/src/api/index.js +8 -0
- package/src/api/index.js.map +1 -0
- package/src/api/use-cases/{api-tags.constants.ts → api-tags.constants.d.ts} +1 -1
- package/src/api/use-cases/api-tags.constants.js +8 -0
- package/src/api/use-cases/api-tags.constants.js.map +1 -0
- package/src/api/use-cases/dismiss/dismiss.controller.d.ts +15 -0
- package/src/api/use-cases/dismiss/dismiss.controller.js +74 -0
- package/src/api/use-cases/dismiss/dismiss.controller.js.map +1 -0
- package/src/api/use-cases/dismiss/dismiss.controller.spec.d.ts +1 -0
- package/src/api/use-cases/dismiss/dismiss.controller.spec.js +37 -0
- package/src/api/use-cases/dismiss/dismiss.controller.spec.js.map +1 -0
- package/src/api/use-cases/dismiss/dismiss.response.dto.d.ts +12 -0
- package/src/api/use-cases/dismiss/dismiss.response.dto.js +12 -0
- package/src/api/use-cases/dismiss/dismiss.response.dto.js.map +1 -0
- package/src/api/use-cases/dismiss/index.js +6 -0
- package/src/api/use-cases/dismiss/index.js.map +1 -0
- package/src/api/use-cases/get-or-create/get-or-create.controller.d.ts +15 -0
- package/src/api/use-cases/get-or-create/get-or-create.controller.js +70 -0
- package/src/api/use-cases/get-or-create/get-or-create.controller.js.map +1 -0
- package/src/api/use-cases/get-or-create/get-or-create.controller.spec.d.ts +1 -0
- package/src/api/use-cases/get-or-create/get-or-create.controller.spec.js +32 -0
- package/src/api/use-cases/get-or-create/get-or-create.controller.spec.js.map +1 -0
- package/src/api/use-cases/get-or-create/get-or-create.response.dto.d.ts +12 -0
- package/src/api/use-cases/get-or-create/get-or-create.response.dto.js +12 -0
- package/src/api/use-cases/get-or-create/get-or-create.response.dto.js.map +1 -0
- package/src/api/use-cases/get-or-create/{index.ts → index.d.ts} +0 -1
- package/src/api/use-cases/get-or-create/index.js +6 -0
- package/src/api/use-cases/get-or-create/index.js.map +1 -0
- package/src/api/use-cases/index.js +7 -0
- package/src/api/use-cases/index.js.map +1 -0
- package/src/api/use-cases/restore/index.js +6 -0
- package/src/api/use-cases/restore/index.js.map +1 -0
- package/src/api/use-cases/restore/restore.controller.d.ts +15 -0
- package/src/api/use-cases/restore/restore.controller.js +74 -0
- package/src/api/use-cases/restore/restore.controller.js.map +1 -0
- package/src/api/use-cases/restore/restore.controller.spec.d.ts +1 -0
- package/src/api/use-cases/restore/restore.controller.spec.js +37 -0
- package/src/api/use-cases/restore/restore.controller.spec.js.map +1 -0
- package/src/api/use-cases/restore/restore.response.dto.d.ts +12 -0
- package/src/api/use-cases/restore/restore.response.dto.js +12 -0
- package/src/api/use-cases/restore/restore.response.dto.js.map +1 -0
- package/src/api/validation/index.d.ts +2 -0
- package/src/api/validation/index.js +6 -0
- package/src/api/validation/index.js.map +1 -0
- package/src/api/validation/param-validation.pipe.d.ts +11 -0
- package/src/api/validation/param-validation.pipe.js +36 -0
- package/src/api/validation/param-validation.pipe.js.map +1 -0
- package/src/api/validation/param-validation.pipe.spec.d.ts +1 -0
- package/src/api/validation/param-validation.pipe.spec.js +269 -0
- package/src/api/validation/param-validation.pipe.spec.js.map +1 -0
- package/src/api/validation/param.decorators.d.ts +28 -0
- package/src/api/validation/param.decorators.js +36 -0
- package/src/api/validation/param.decorators.js.map +1 -0
- package/src/core/dismissible-core.service.d.ts +56 -0
- package/src/core/dismissible-core.service.js +147 -0
- package/src/core/dismissible-core.service.js.map +1 -0
- package/src/core/dismissible-core.service.spec.d.ts +1 -0
- package/src/core/dismissible-core.service.spec.js +309 -0
- package/src/core/dismissible-core.service.spec.js.map +1 -0
- package/src/core/dismissible.service.d.ts +45 -0
- package/src/core/dismissible.service.js +127 -0
- package/src/core/dismissible.service.js.map +1 -0
- package/src/core/dismissible.service.spec.d.ts +1 -0
- package/src/core/dismissible.service.spec.js +159 -0
- package/src/core/dismissible.service.spec.js.map +1 -0
- package/src/core/hook-runner.service.d.ts +88 -0
- package/src/core/hook-runner.service.js +226 -0
- package/src/core/hook-runner.service.js.map +1 -0
- package/src/core/hook-runner.service.spec.d.ts +1 -0
- package/src/core/hook-runner.service.spec.js +538 -0
- package/src/core/hook-runner.service.spec.js.map +1 -0
- package/src/core/{index.ts → index.d.ts} +0 -1
- package/src/core/index.js +9 -0
- package/src/core/index.js.map +1 -0
- package/src/core/lifecycle-hook.interface.d.ts +1 -0
- package/src/core/lifecycle-hook.interface.js +7 -0
- package/src/core/lifecycle-hook.interface.js.map +1 -0
- package/src/core/service-responses.interface.d.ts +28 -0
- package/src/core/service-responses.interface.js +3 -0
- package/src/core/service-responses.interface.js.map +1 -0
- package/src/dismissible.module.d.ts +13 -0
- package/src/dismissible.module.integration.spec.d.ts +1 -0
- package/src/dismissible.module.integration.spec.js +529 -0
- package/src/dismissible.module.integration.spec.js.map +1 -0
- package/src/dismissible.module.js +77 -0
- package/src/dismissible.module.js.map +1 -0
- package/src/events/dismissible.events.d.ts +45 -0
- package/src/events/dismissible.events.js +53 -0
- package/src/events/dismissible.events.js.map +1 -0
- package/src/events/events.constants.d.ts +17 -0
- package/src/events/events.constants.js +17 -0
- package/src/events/events.constants.js.map +1 -0
- package/src/events/index.js +6 -0
- package/src/events/index.js.map +1 -0
- package/src/exceptions/dismissible.exceptions.d.ts +26 -0
- package/src/exceptions/dismissible.exceptions.js +49 -0
- package/src/exceptions/dismissible.exceptions.js.map +1 -0
- package/src/exceptions/dismissible.exceptions.spec.d.ts +1 -0
- package/src/exceptions/dismissible.exceptions.spec.js +40 -0
- package/src/exceptions/dismissible.exceptions.spec.js.map +1 -0
- package/src/exceptions/index.js +5 -0
- package/src/exceptions/index.js.map +1 -0
- package/src/{index.ts → index.d.ts} +1 -1
- package/src/index.js +12 -0
- package/src/index.js.map +1 -0
- package/src/response/dtos/base-response.dto.d.ts +6 -0
- package/src/response/dtos/base-response.dto.js +18 -0
- package/src/response/dtos/base-response.dto.js.map +1 -0
- package/src/response/dtos/error-response.dto.d.ts +19 -0
- package/src/response/dtos/error-response.dto.js +39 -0
- package/src/response/dtos/error-response.dto.js.map +1 -0
- package/src/response/dtos/index.js +7 -0
- package/src/response/dtos/index.js.map +1 -0
- package/src/response/dtos/{success-response.dto.ts → success-response.dto.d.ts} +6 -12
- package/src/response/dtos/success-response.dto.js +34 -0
- package/src/response/dtos/success-response.dto.js.map +1 -0
- package/src/response/http-exception-filter.d.ts +4 -0
- package/src/response/http-exception-filter.js +24 -0
- package/src/response/http-exception-filter.js.map +1 -0
- package/src/response/http-exception-filter.spec.d.ts +1 -0
- package/src/response/http-exception-filter.spec.js +137 -0
- package/src/response/http-exception-filter.spec.js.map +1 -0
- package/src/response/index.js +8 -0
- package/src/response/index.js.map +1 -0
- package/src/response/response.module.d.ts +2 -0
- package/src/response/response.module.js +17 -0
- package/src/response/response.module.js.map +1 -0
- package/src/response/response.service.d.ts +6 -0
- package/src/response/response.service.js +25 -0
- package/src/response/response.service.js.map +1 -0
- package/src/response/response.service.spec.d.ts +1 -0
- package/src/response/response.service.spec.js +58 -0
- package/src/response/response.service.spec.js.map +1 -0
- package/src/testing/factories.d.ts +14 -0
- package/src/testing/factories.js +58 -0
- package/src/testing/factories.js.map +1 -0
- package/src/testing/index.js +5 -0
- package/src/testing/index.js.map +1 -0
- package/src/utils/date/date.service.d.ts +8 -0
- package/src/utils/date/date.service.js +24 -0
- package/src/utils/date/date.service.js.map +1 -0
- package/src/utils/date/date.service.spec.d.ts +1 -0
- package/src/utils/date/date.service.spec.js +83 -0
- package/src/utils/date/date.service.spec.js.map +1 -0
- package/src/utils/date/index.js +5 -0
- package/src/utils/date/index.js.map +1 -0
- package/src/utils/dismissible.helper.d.ts +4 -0
- package/src/utils/dismissible.helper.js +15 -0
- package/src/utils/dismissible.helper.js.map +1 -0
- package/src/utils/index.js +7 -0
- package/src/utils/index.js.map +1 -0
- package/src/validation/dismissible-input.dto.d.ts +21 -0
- package/src/validation/dismissible-input.dto.js +54 -0
- package/src/validation/dismissible-input.dto.js.map +1 -0
- package/src/validation/index.d.ts +1 -0
- package/src/validation/index.js +5 -0
- package/src/validation/index.js.map +1 -0
- package/jest.config.ts +0 -29
- package/project.json +0 -42
- package/src/api/dismissible-item-response.dto.ts +0 -38
- package/src/api/dismissible-item.mapper.spec.ts +0 -63
- package/src/api/dismissible-item.mapper.ts +0 -33
- package/src/api/use-cases/dismiss/dismiss.controller.spec.ts +0 -42
- package/src/api/use-cases/dismiss/dismiss.controller.ts +0 -63
- package/src/api/use-cases/dismiss/dismiss.response.dto.ts +0 -7
- package/src/api/use-cases/get-or-create/get-or-create.controller.spec.ts +0 -76
- package/src/api/use-cases/get-or-create/get-or-create.controller.ts +0 -106
- package/src/api/use-cases/get-or-create/get-or-create.request.dto.ts +0 -17
- package/src/api/use-cases/get-or-create/get-or-create.response.dto.ts +0 -7
- package/src/api/use-cases/restore/restore.controller.spec.ts +0 -42
- package/src/api/use-cases/restore/restore.controller.ts +0 -63
- package/src/api/use-cases/restore/restore.response.dto.ts +0 -7
- package/src/core/create-options.ts +0 -9
- package/src/core/dismissible-core.service.spec.ts +0 -357
- package/src/core/dismissible-core.service.ts +0 -161
- package/src/core/dismissible.service.spec.ts +0 -144
- package/src/core/dismissible.service.ts +0 -188
- package/src/core/hook-runner.service.spec.ts +0 -304
- package/src/core/hook-runner.service.ts +0 -267
- package/src/core/lifecycle-hook.interface.ts +0 -122
- package/src/core/service-responses.interface.ts +0 -34
- package/src/dismissible.module.ts +0 -83
- package/src/events/dismissible.events.ts +0 -105
- package/src/events/events.constants.ts +0 -21
- package/src/exceptions/dismissible.exceptions.spec.ts +0 -50
- package/src/exceptions/dismissible.exceptions.ts +0 -69
- package/src/request/index.ts +0 -2
- package/src/request/request-context.decorator.ts +0 -14
- package/src/request/request-context.interface.ts +0 -6
- package/src/response/dtos/base-response.dto.ts +0 -11
- package/src/response/dtos/error-response.dto.ts +0 -36
- package/src/response/http-exception-filter.ts +0 -21
- package/src/response/response.module.ts +0 -9
- package/src/response/response.service.spec.ts +0 -86
- package/src/response/response.service.ts +0 -20
- package/src/testing/factories.ts +0 -45
- package/src/utils/date/date.service.spec.ts +0 -104
- package/src/utils/date/date.service.ts +0 -19
- package/src/utils/dismissible.helper.ts +0 -9
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -14
- /package/src/api/use-cases/dismiss/{index.ts → index.d.ts} +0 -0
- /package/src/api/use-cases/{index.ts → index.d.ts} +0 -0
- /package/src/api/use-cases/restore/{index.ts → index.d.ts} +0 -0
- /package/src/events/{index.ts → index.d.ts} +0 -0
- /package/src/exceptions/{index.ts → index.d.ts} +0 -0
- /package/src/response/dtos/{index.ts → index.d.ts} +0 -0
- /package/src/response/{index.ts → index.d.ts} +0 -0
- /package/src/testing/{index.ts → index.d.ts} +0 -0
- /package/src/utils/date/{index.ts → index.d.ts} +0 -0
- /package/src/utils/{index.ts → index.d.ts} +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DismissibleInputDto = exports.VALIDATION_CONSTANTS = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const class_validator_1 = require("class-validator");
|
|
6
|
+
/**
|
|
7
|
+
* Validation constants for dismissible input fields.
|
|
8
|
+
*/
|
|
9
|
+
exports.VALIDATION_CONSTANTS = {
|
|
10
|
+
/** Maximum length for userId and itemId */
|
|
11
|
+
ID_MAX_LENGTH: 64,
|
|
12
|
+
/** Minimum length for userId and itemId */
|
|
13
|
+
ID_MIN_LENGTH: 1,
|
|
14
|
+
/** Pattern for valid userId and itemId (alphanumeric, dash, underscore) */
|
|
15
|
+
ID_PATTERN: /^[a-zA-Z0-9_-]+$/,
|
|
16
|
+
/** Human-readable description of the ID pattern */
|
|
17
|
+
ID_PATTERN_MESSAGE: 'must contain only alphanumeric characters, dashes, and underscores',
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* DTO for validating dismissible input parameters (userId and itemId).
|
|
21
|
+
* Used at both controller and service layers for defense in depth.
|
|
22
|
+
*/
|
|
23
|
+
class DismissibleInputDto {
|
|
24
|
+
}
|
|
25
|
+
exports.DismissibleInputDto = DismissibleInputDto;
|
|
26
|
+
tslib_1.__decorate([
|
|
27
|
+
(0, class_validator_1.IsString)(),
|
|
28
|
+
(0, class_validator_1.IsNotEmpty)({ message: 'itemId is required' }),
|
|
29
|
+
(0, class_validator_1.MinLength)(exports.VALIDATION_CONSTANTS.ID_MIN_LENGTH, {
|
|
30
|
+
message: `itemId must be at least ${exports.VALIDATION_CONSTANTS.ID_MIN_LENGTH} character`,
|
|
31
|
+
}),
|
|
32
|
+
(0, class_validator_1.MaxLength)(exports.VALIDATION_CONSTANTS.ID_MAX_LENGTH, {
|
|
33
|
+
message: `itemId must be at most ${exports.VALIDATION_CONSTANTS.ID_MAX_LENGTH} characters`,
|
|
34
|
+
}),
|
|
35
|
+
(0, class_validator_1.Matches)(exports.VALIDATION_CONSTANTS.ID_PATTERN, {
|
|
36
|
+
message: `itemId ${exports.VALIDATION_CONSTANTS.ID_PATTERN_MESSAGE}`,
|
|
37
|
+
}),
|
|
38
|
+
tslib_1.__metadata("design:type", String)
|
|
39
|
+
], DismissibleInputDto.prototype, "itemId", void 0);
|
|
40
|
+
tslib_1.__decorate([
|
|
41
|
+
(0, class_validator_1.IsString)(),
|
|
42
|
+
(0, class_validator_1.IsNotEmpty)({ message: 'userId is required' }),
|
|
43
|
+
(0, class_validator_1.MinLength)(exports.VALIDATION_CONSTANTS.ID_MIN_LENGTH, {
|
|
44
|
+
message: `userId must be at least ${exports.VALIDATION_CONSTANTS.ID_MIN_LENGTH} character`,
|
|
45
|
+
}),
|
|
46
|
+
(0, class_validator_1.MaxLength)(exports.VALIDATION_CONSTANTS.ID_MAX_LENGTH, {
|
|
47
|
+
message: `userId must be at most ${exports.VALIDATION_CONSTANTS.ID_MAX_LENGTH} characters`,
|
|
48
|
+
}),
|
|
49
|
+
(0, class_validator_1.Matches)(exports.VALIDATION_CONSTANTS.ID_PATTERN, {
|
|
50
|
+
message: `userId ${exports.VALIDATION_CONSTANTS.ID_PATTERN_MESSAGE}`,
|
|
51
|
+
}),
|
|
52
|
+
tslib_1.__metadata("design:type", String)
|
|
53
|
+
], DismissibleInputDto.prototype, "userId", void 0);
|
|
54
|
+
//# sourceMappingURL=dismissible-input.dto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dismissible-input.dto.js","sourceRoot":"","sources":["../../../../../libs/dismissible/src/validation/dismissible-input.dto.ts"],"names":[],"mappings":";;;;AAAA,qDAAsF;AAEtF;;GAEG;AACU,QAAA,oBAAoB,GAAG;IAClC,2CAA2C;IAC3C,aAAa,EAAE,EAAE;IACjB,2CAA2C;IAC3C,aAAa,EAAE,CAAC;IAChB,2EAA2E;IAC3E,UAAU,EAAE,kBAAkB;IAC9B,mDAAmD;IACnD,kBAAkB,EAAE,oEAAoE;CAChF,CAAC;AAEX;;;GAGG;AACH,MAAa,mBAAmB;CA0B/B;AA1BD,kDA0BC;AAdC;IAXC,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAC7C,IAAA,2BAAS,EAAC,4BAAoB,CAAC,aAAa,EAAE;QAC7C,OAAO,EAAE,2BAA2B,4BAAoB,CAAC,aAAa,YAAY;KACnF,CAAC;IACD,IAAA,2BAAS,EAAC,4BAAoB,CAAC,aAAa,EAAE;QAC7C,OAAO,EAAE,0BAA0B,4BAAoB,CAAC,aAAa,aAAa;KACnF,CAAC;IACD,IAAA,yBAAO,EAAC,4BAAoB,CAAC,UAAU,EAAE;QACxC,OAAO,EAAE,UAAU,4BAAoB,CAAC,kBAAkB,EAAE;KAC7D,CAAC;;mDACa;AAaf;IAXC,IAAA,0BAAQ,GAAE;IACV,IAAA,4BAAU,EAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC;IAC7C,IAAA,2BAAS,EAAC,4BAAoB,CAAC,aAAa,EAAE;QAC7C,OAAO,EAAE,2BAA2B,4BAAoB,CAAC,aAAa,YAAY;KACnF,CAAC;IACD,IAAA,2BAAS,EAAC,4BAAoB,CAAC,aAAa,EAAE;QAC7C,OAAO,EAAE,0BAA0B,4BAAoB,CAAC,aAAa,aAAa;KACnF,CAAC;IACD,IAAA,yBAAO,EAAC,4BAAoB,CAAC,UAAU,EAAE;QACxC,OAAO,EAAE,UAAU,4BAAoB,CAAC,kBAAkB,EAAE;KAC7D,CAAC;;mDACa"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dismissible-input.dto';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../libs/dismissible/src/validation/index.ts"],"names":[],"mappings":";;;AAAA,kEAAwC"}
|
package/jest.config.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
displayName: 'dismissible',
|
|
3
|
-
preset: '../../jest.preset.js',
|
|
4
|
-
testEnvironment: 'node',
|
|
5
|
-
transform: {
|
|
6
|
-
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.json' }],
|
|
7
|
-
},
|
|
8
|
-
moduleFileExtensions: ['ts', 'js', 'html'],
|
|
9
|
-
coverageDirectory: '../../coverage/libs/dismissible',
|
|
10
|
-
transformIgnorePatterns: ['node_modules/(?!(uuid)/)'],
|
|
11
|
-
collectCoverageFrom: [
|
|
12
|
-
'src/**/*.ts',
|
|
13
|
-
'!src/**/*.spec.ts',
|
|
14
|
-
'!src/**/*.interface.ts',
|
|
15
|
-
'!src/**/*.dto.ts',
|
|
16
|
-
'!src/**/*.enum.ts',
|
|
17
|
-
'!src/**/index.ts',
|
|
18
|
-
'!src/**/*.module.ts',
|
|
19
|
-
],
|
|
20
|
-
coverageReporters: ['text', 'text-summary', 'html'],
|
|
21
|
-
coverageThreshold: {
|
|
22
|
-
global: {
|
|
23
|
-
branches: 81,
|
|
24
|
-
functions: 84,
|
|
25
|
-
lines: 92,
|
|
26
|
-
statements: 92,
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
};
|
package/project.json
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dismissible",
|
|
3
|
-
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
-
"sourceRoot": "libs/dismissible/src",
|
|
5
|
-
"projectType": "library",
|
|
6
|
-
"tags": [],
|
|
7
|
-
"targets": {
|
|
8
|
-
"build": {
|
|
9
|
-
"executor": "@nx/js:tsc",
|
|
10
|
-
"outputs": ["{options.outputPath}"],
|
|
11
|
-
"options": {
|
|
12
|
-
"outputPath": "dist/libs/dismissible",
|
|
13
|
-
"main": "libs/dismissible/src/index.ts",
|
|
14
|
-
"tsConfig": "libs/dismissible/tsconfig.lib.json",
|
|
15
|
-
"assets": ["libs/dismissible/package.json", "libs/dismissible/README.md"],
|
|
16
|
-
"generatePackageJson": true
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"lint": {
|
|
20
|
-
"executor": "@nx/eslint:lint",
|
|
21
|
-
"outputs": ["{options.outputFile}"],
|
|
22
|
-
"options": {
|
|
23
|
-
"lintFilePatterns": ["libs/dismissible/**/*.ts"]
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
"test": {
|
|
27
|
-
"executor": "@nx/jest:jest",
|
|
28
|
-
"outputs": ["{workspaceRoot}/coverage/libs/dismissible"],
|
|
29
|
-
"options": {
|
|
30
|
-
"jestConfig": "libs/dismissible/jest.config.ts",
|
|
31
|
-
"passWithNoTests": true
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
"npm-publish": {
|
|
35
|
-
"executor": "nx:run-commands",
|
|
36
|
-
"options": {
|
|
37
|
-
"command": "npm publish --access public",
|
|
38
|
-
"cwd": "dist/libs/dismissible"
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Response DTO for a dismissible item.
|
|
5
|
-
*/
|
|
6
|
-
export class DismissibleItemResponseDto {
|
|
7
|
-
@ApiProperty({
|
|
8
|
-
description: 'Unique identifier for the item',
|
|
9
|
-
example: 'welcome-banner-v2',
|
|
10
|
-
})
|
|
11
|
-
itemId!: string;
|
|
12
|
-
|
|
13
|
-
@ApiProperty({
|
|
14
|
-
description: 'User identifier who created the item',
|
|
15
|
-
example: 'user-123',
|
|
16
|
-
})
|
|
17
|
-
userId!: string;
|
|
18
|
-
|
|
19
|
-
@ApiProperty({
|
|
20
|
-
description: 'When the item was created (ISO 8601)',
|
|
21
|
-
example: '2024-01-15T10:30:00.000Z',
|
|
22
|
-
})
|
|
23
|
-
createdAt!: string;
|
|
24
|
-
|
|
25
|
-
@ApiPropertyOptional({
|
|
26
|
-
description: 'When the item was dismissed (ISO 8601)',
|
|
27
|
-
example: '2024-01-15T12:00:00.000Z',
|
|
28
|
-
})
|
|
29
|
-
dismissedAt?: string;
|
|
30
|
-
|
|
31
|
-
@ApiPropertyOptional({
|
|
32
|
-
description: 'Optional metadata associated with the item',
|
|
33
|
-
example: { version: 2, category: 'promotional' },
|
|
34
|
-
type: 'object',
|
|
35
|
-
additionalProperties: true,
|
|
36
|
-
})
|
|
37
|
-
metadata?: Record<string, unknown>;
|
|
38
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { DismissibleItemMapper } from './dismissible-item.mapper';
|
|
2
|
-
import { createTestItem, createDismissedTestItem } from '../testing/factories';
|
|
3
|
-
|
|
4
|
-
describe('DismissibleItemMapper', () => {
|
|
5
|
-
let mapper: DismissibleItemMapper;
|
|
6
|
-
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
mapper = new DismissibleItemMapper();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
describe('toResponseDto', () => {
|
|
12
|
-
it('should convert basic item to DTO', () => {
|
|
13
|
-
const item = createTestItem({
|
|
14
|
-
id: 'test-item',
|
|
15
|
-
userId: 'test-user-id',
|
|
16
|
-
createdAt: new Date('2024-01-15T10:00:00.000Z'),
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const dto = mapper.toResponseDto(item);
|
|
20
|
-
|
|
21
|
-
expect(dto.itemId).toBe('test-item');
|
|
22
|
-
expect(dto.userId).toBe('test-user-id');
|
|
23
|
-
expect(dto.createdAt).toBe('2024-01-15T10:00:00.000Z');
|
|
24
|
-
expect(dto.dismissedAt).toBeUndefined();
|
|
25
|
-
expect(dto.metadata).toBeUndefined();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should convert dates to ISO strings', () => {
|
|
29
|
-
const item = createDismissedTestItem({
|
|
30
|
-
id: 'test-item',
|
|
31
|
-
createdAt: new Date('2024-01-15T10:00:00.000Z'),
|
|
32
|
-
dismissedAt: new Date('2024-01-15T12:00:00.000Z'),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
const dto = mapper.toResponseDto(item);
|
|
36
|
-
|
|
37
|
-
expect(dto.createdAt).toBe('2024-01-15T10:00:00.000Z');
|
|
38
|
-
expect(dto.dismissedAt).toBe('2024-01-15T12:00:00.000Z');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should include userId in DTO', () => {
|
|
42
|
-
const item = createTestItem({
|
|
43
|
-
id: 'test-item',
|
|
44
|
-
userId: 'user-123',
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const dto = mapper.toResponseDto(item);
|
|
48
|
-
|
|
49
|
-
expect(dto.userId).toBe('user-123');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should include metadata when present', () => {
|
|
53
|
-
const item = createTestItem({
|
|
54
|
-
id: 'test-item',
|
|
55
|
-
metadata: { version: 2, category: 'test' },
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
const dto = mapper.toResponseDto(item);
|
|
59
|
-
|
|
60
|
-
expect(dto.metadata).toEqual({ version: 2, category: 'test' });
|
|
61
|
-
});
|
|
62
|
-
});
|
|
63
|
-
});
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@nestjs/common';
|
|
2
|
-
import { BaseMetadata, DismissibleItemDto } from '@dismissible/nestjs-dismissible-item';
|
|
3
|
-
import { DismissibleItemResponseDto } from './dismissible-item-response.dto';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Mapper for converting domain objects to DTOs.
|
|
7
|
-
*/
|
|
8
|
-
@Injectable()
|
|
9
|
-
export class DismissibleItemMapper {
|
|
10
|
-
/**
|
|
11
|
-
* Convert a dismissible item to a response DTO.
|
|
12
|
-
* Converts Date objects to ISO 8601 strings.
|
|
13
|
-
*/
|
|
14
|
-
toResponseDto<TMetadata extends BaseMetadata>(
|
|
15
|
-
item: DismissibleItemDto<TMetadata>,
|
|
16
|
-
): DismissibleItemResponseDto {
|
|
17
|
-
const dto = new DismissibleItemResponseDto();
|
|
18
|
-
|
|
19
|
-
dto.itemId = item.id;
|
|
20
|
-
dto.userId = item.userId;
|
|
21
|
-
dto.createdAt = item.createdAt.toISOString();
|
|
22
|
-
|
|
23
|
-
if (item.dismissedAt) {
|
|
24
|
-
dto.dismissedAt = item.dismissedAt.toISOString();
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (item.metadata) {
|
|
28
|
-
dto.metadata = item.metadata as Record<string, unknown>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return dto;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { mock } from 'ts-jest-mocker';
|
|
2
|
-
import { DismissController } from './dismiss.controller';
|
|
3
|
-
import { DismissibleService } from '../../../core/dismissible.service';
|
|
4
|
-
import { DismissibleItemMapper } from '../../dismissible-item.mapper';
|
|
5
|
-
import { BaseMetadata } from '@dismissible/nestjs-dismissible-item';
|
|
6
|
-
import { createTestItem, createTestContext } from '../../../testing/factories';
|
|
7
|
-
import { ResponseService } from '../../../response';
|
|
8
|
-
|
|
9
|
-
describe('DismissController', () => {
|
|
10
|
-
let controller: DismissController;
|
|
11
|
-
let mockService: jest.Mocked<DismissibleService<BaseMetadata>>;
|
|
12
|
-
let mockResponseService: jest.Mocked<ResponseService>;
|
|
13
|
-
let mapper: DismissibleItemMapper;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
mockService = mock(DismissibleService);
|
|
17
|
-
mockResponseService = mock(ResponseService, { failIfMockNotProvided: false });
|
|
18
|
-
mockResponseService.success.mockImplementation((data) => ({ data }));
|
|
19
|
-
mapper = new DismissibleItemMapper();
|
|
20
|
-
|
|
21
|
-
controller = new DismissController(mockService, mapper, mockResponseService);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe('dismiss', () => {
|
|
25
|
-
it('should return dismissed item wrapped in data', async () => {
|
|
26
|
-
const item = createTestItem({
|
|
27
|
-
id: 'test-item',
|
|
28
|
-
dismissedAt: new Date(),
|
|
29
|
-
});
|
|
30
|
-
const previousItem = createTestItem({ id: 'test-item' });
|
|
31
|
-
const context = createTestContext();
|
|
32
|
-
|
|
33
|
-
mockService.dismiss.mockResolvedValue({ item, previousItem });
|
|
34
|
-
|
|
35
|
-
const result = await controller.dismiss('test-user-id', 'test-item', context);
|
|
36
|
-
|
|
37
|
-
expect(result.data.itemId).toBe('test-item');
|
|
38
|
-
expect(mockService.dismiss).toHaveBeenCalledWith('test-item', 'test-user-id', context);
|
|
39
|
-
expect(mockResponseService.success).toHaveBeenCalled();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
});
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { Controller, Delete, Param, UseFilters } from '@nestjs/common';
|
|
2
|
-
import { ApiTags, ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger';
|
|
3
|
-
import { DismissibleService } from '../../../core/dismissible.service';
|
|
4
|
-
import { DismissibleItemMapper } from '../../dismissible-item.mapper';
|
|
5
|
-
import { RequestContext } from '../../../request/request-context.decorator';
|
|
6
|
-
import { IRequestContext } from '../../../request/request-context.interface';
|
|
7
|
-
import { BaseMetadata } from '@dismissible/nestjs-dismissible-item';
|
|
8
|
-
import { DismissResponseDto } from './dismiss.response.dto';
|
|
9
|
-
import { ResponseService } from '../../../response/response.service';
|
|
10
|
-
import { HttpExceptionFilter } from '../../../response/http-exception-filter';
|
|
11
|
-
import { API_TAG_DISMISSIBLE } from '../api-tags.constants';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Controller for dismiss dismissible item operations.
|
|
15
|
-
*/
|
|
16
|
-
@ApiTags(API_TAG_DISMISSIBLE)
|
|
17
|
-
@Controller('v1/user/:userId/dismissible-item')
|
|
18
|
-
export class DismissController {
|
|
19
|
-
constructor(
|
|
20
|
-
private readonly dismissibleService: DismissibleService<BaseMetadata>,
|
|
21
|
-
private readonly mapper: DismissibleItemMapper,
|
|
22
|
-
private readonly responseService: ResponseService,
|
|
23
|
-
) {}
|
|
24
|
-
|
|
25
|
-
@Delete(':itemId')
|
|
26
|
-
@ApiOperation({
|
|
27
|
-
summary: 'Dismiss an item',
|
|
28
|
-
description: 'Marks a dismissible item as dismissed.',
|
|
29
|
-
})
|
|
30
|
-
@ApiParam({
|
|
31
|
-
name: 'userId',
|
|
32
|
-
description: 'User identifier',
|
|
33
|
-
example: 'user-123',
|
|
34
|
-
})
|
|
35
|
-
@ApiParam({
|
|
36
|
-
name: 'itemId',
|
|
37
|
-
description: 'Unique identifier for the dismissible item',
|
|
38
|
-
example: 'welcome-banner-v2',
|
|
39
|
-
})
|
|
40
|
-
@ApiResponse({
|
|
41
|
-
status: 200,
|
|
42
|
-
description: 'The dismissed item',
|
|
43
|
-
type: DismissResponseDto,
|
|
44
|
-
})
|
|
45
|
-
@ApiResponse({
|
|
46
|
-
status: 400,
|
|
47
|
-
description: 'Item not found or already dismissed',
|
|
48
|
-
})
|
|
49
|
-
@ApiResponse({
|
|
50
|
-
status: 403,
|
|
51
|
-
description: 'Operation blocked by lifecycle hook',
|
|
52
|
-
})
|
|
53
|
-
@UseFilters(HttpExceptionFilter)
|
|
54
|
-
async dismiss(
|
|
55
|
-
@Param('userId') userId: string,
|
|
56
|
-
@Param('itemId') itemId: string,
|
|
57
|
-
@RequestContext() context: IRequestContext,
|
|
58
|
-
): Promise<DismissResponseDto> {
|
|
59
|
-
const result = await this.dismissibleService.dismiss(itemId, userId, context);
|
|
60
|
-
|
|
61
|
-
return this.responseService.success(this.mapper.toResponseDto(result.item));
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { SuccessResponseDto } from '../../../response/dtos/success-response.dto';
|
|
2
|
-
import { DismissibleItemResponseDto } from '../../dismissible-item-response.dto';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Response DTO for the dismiss operation.
|
|
6
|
-
*/
|
|
7
|
-
export class DismissResponseDto extends SuccessResponseDto(DismissibleItemResponseDto) {}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { mock } from 'ts-jest-mocker';
|
|
2
|
-
import { GetOrCreateController } from './get-or-create.controller';
|
|
3
|
-
import { DismissibleService } from '../../../core/dismissible.service';
|
|
4
|
-
import { DismissibleItemMapper } from '../../dismissible-item.mapper';
|
|
5
|
-
import { BaseMetadata } from '@dismissible/nestjs-dismissible-item';
|
|
6
|
-
import { createTestItem, createTestContext } from '../../../testing/factories';
|
|
7
|
-
import { ResponseService } from '../../../response';
|
|
8
|
-
|
|
9
|
-
describe('GetOrCreateController', () => {
|
|
10
|
-
let controller: GetOrCreateController;
|
|
11
|
-
let mockService: jest.Mocked<DismissibleService<BaseMetadata>>;
|
|
12
|
-
let mockResponseService: jest.Mocked<ResponseService>;
|
|
13
|
-
let mapper: DismissibleItemMapper;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
mockService = mock(DismissibleService);
|
|
17
|
-
mockResponseService = mock(ResponseService, { failIfMockNotProvided: false });
|
|
18
|
-
mockResponseService.success.mockImplementation((data) => ({ data }));
|
|
19
|
-
mapper = new DismissibleItemMapper();
|
|
20
|
-
|
|
21
|
-
controller = new GetOrCreateController(mockService, mapper, mockResponseService);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe('getOrCreate', () => {
|
|
25
|
-
it('should return item with created flag wrapped in data', async () => {
|
|
26
|
-
const item = createTestItem({ id: 'test-item' });
|
|
27
|
-
const context = createTestContext();
|
|
28
|
-
|
|
29
|
-
mockService.getOrCreate.mockResolvedValue({ item, created: true });
|
|
30
|
-
|
|
31
|
-
const result = await controller.getOrCreate('test-user-id', 'test-item', context, undefined);
|
|
32
|
-
|
|
33
|
-
expect(result.data.itemId).toBe('test-item');
|
|
34
|
-
expect(mockResponseService.success).toHaveBeenCalled();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should parse metadata from query params', async () => {
|
|
38
|
-
const item = createTestItem({ id: 'test-item' });
|
|
39
|
-
const context = createTestContext();
|
|
40
|
-
|
|
41
|
-
mockService.getOrCreate.mockResolvedValue({ item, created: true });
|
|
42
|
-
|
|
43
|
-
await controller.getOrCreate('test-user-id', 'test-item', context, [
|
|
44
|
-
'version:2',
|
|
45
|
-
'category:test',
|
|
46
|
-
]);
|
|
47
|
-
|
|
48
|
-
expect(mockService.getOrCreate).toHaveBeenCalledWith(
|
|
49
|
-
'test-item',
|
|
50
|
-
'test-user-id',
|
|
51
|
-
expect.objectContaining({
|
|
52
|
-
metadata: { version: 2, category: 'test' },
|
|
53
|
-
}),
|
|
54
|
-
context,
|
|
55
|
-
);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('should handle single metadata value', async () => {
|
|
59
|
-
const item = createTestItem({ id: 'test-item' });
|
|
60
|
-
const context = createTestContext();
|
|
61
|
-
|
|
62
|
-
mockService.getOrCreate.mockResolvedValue({ item, created: true });
|
|
63
|
-
|
|
64
|
-
await controller.getOrCreate('test-user-id', 'test-item', context, 'version:2');
|
|
65
|
-
|
|
66
|
-
expect(mockService.getOrCreate).toHaveBeenCalledWith(
|
|
67
|
-
'test-item',
|
|
68
|
-
'test-user-id',
|
|
69
|
-
expect.objectContaining({
|
|
70
|
-
metadata: { version: 2 },
|
|
71
|
-
}),
|
|
72
|
-
context,
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
});
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
import { Controller, Get, Param, Query, UseFilters } from '@nestjs/common';
|
|
2
|
-
import { ApiTags, ApiOperation, ApiParam, ApiResponse, ApiQuery } from '@nestjs/swagger';
|
|
3
|
-
import { DismissibleService } from '../../../core/dismissible.service';
|
|
4
|
-
import { DismissibleItemMapper } from '../../dismissible-item.mapper';
|
|
5
|
-
import { RequestContext } from '../../../request/request-context.decorator';
|
|
6
|
-
import { IRequestContext } from '../../../request/request-context.interface';
|
|
7
|
-
import { BaseMetadata } from '@dismissible/nestjs-dismissible-item';
|
|
8
|
-
import { GetOrCreateResponseDto } from './get-or-create.response.dto';
|
|
9
|
-
import { ResponseService } from '../../../response/response.service';
|
|
10
|
-
import { HttpExceptionFilter } from '../../../response/http-exception-filter';
|
|
11
|
-
import { API_TAG_DISMISSIBLE } from '../api-tags.constants';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Controller for get-or-create dismissible item operations.
|
|
15
|
-
*/
|
|
16
|
-
@ApiTags(API_TAG_DISMISSIBLE)
|
|
17
|
-
@Controller('v1/user/:userId/dismissible-item')
|
|
18
|
-
export class GetOrCreateController {
|
|
19
|
-
constructor(
|
|
20
|
-
private readonly dismissibleService: DismissibleService<BaseMetadata>,
|
|
21
|
-
private readonly mapper: DismissibleItemMapper,
|
|
22
|
-
private readonly responseService: ResponseService,
|
|
23
|
-
) {}
|
|
24
|
-
|
|
25
|
-
@Get(':itemId')
|
|
26
|
-
@ApiOperation({
|
|
27
|
-
summary: 'Get or create a dismissible item',
|
|
28
|
-
description:
|
|
29
|
-
'Retrieves an existing dismissible item by ID, or creates a new one if it does not exist.',
|
|
30
|
-
})
|
|
31
|
-
@ApiParam({
|
|
32
|
-
name: 'userId',
|
|
33
|
-
description: 'User identifier',
|
|
34
|
-
example: 'user-123',
|
|
35
|
-
})
|
|
36
|
-
@ApiParam({
|
|
37
|
-
name: 'itemId',
|
|
38
|
-
description: 'Unique identifier for the dismissible item',
|
|
39
|
-
example: 'welcome-banner-v2',
|
|
40
|
-
})
|
|
41
|
-
@ApiQuery({
|
|
42
|
-
name: 'metadata',
|
|
43
|
-
description: 'Optional metadata as key:value pairs (can be repeated)',
|
|
44
|
-
required: false,
|
|
45
|
-
isArray: true,
|
|
46
|
-
type: String,
|
|
47
|
-
example: 'version:2',
|
|
48
|
-
})
|
|
49
|
-
@ApiResponse({
|
|
50
|
-
status: 200,
|
|
51
|
-
description: 'The dismissible item (retrieved or created)',
|
|
52
|
-
type: GetOrCreateResponseDto,
|
|
53
|
-
})
|
|
54
|
-
@ApiResponse({
|
|
55
|
-
status: 403,
|
|
56
|
-
description: 'Operation blocked by lifecycle hook',
|
|
57
|
-
})
|
|
58
|
-
@UseFilters(HttpExceptionFilter)
|
|
59
|
-
async getOrCreate(
|
|
60
|
-
@Param('userId') userId: string,
|
|
61
|
-
@Param('itemId') itemId: string,
|
|
62
|
-
@RequestContext() context: IRequestContext,
|
|
63
|
-
@Query('metadata') metadataRaw?: string | string[],
|
|
64
|
-
): Promise<GetOrCreateResponseDto> {
|
|
65
|
-
// Parse metadata from query params
|
|
66
|
-
const metadata = this.parseMetadata(metadataRaw);
|
|
67
|
-
|
|
68
|
-
const result = await this.dismissibleService.getOrCreate(
|
|
69
|
-
itemId,
|
|
70
|
-
userId,
|
|
71
|
-
{
|
|
72
|
-
metadata: metadata as BaseMetadata,
|
|
73
|
-
},
|
|
74
|
-
context,
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
return this.responseService.success(this.mapper.toResponseDto(result.item));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Parse metadata from query parameter format.
|
|
82
|
-
* Supports: `?metadata=key1:value1&metadata=key2:value2`
|
|
83
|
-
*/
|
|
84
|
-
private parseMetadata(raw?: string | string[]): Record<string, string | number> | undefined {
|
|
85
|
-
if (!raw) {
|
|
86
|
-
return undefined;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const items = Array.isArray(raw) ? raw : [raw];
|
|
90
|
-
const metadata: Record<string, string | number> = {};
|
|
91
|
-
|
|
92
|
-
for (const item of items) {
|
|
93
|
-
const colonIndex = item.indexOf(':');
|
|
94
|
-
if (colonIndex > 0) {
|
|
95
|
-
const key = item.substring(0, colonIndex);
|
|
96
|
-
const value = item.substring(colonIndex + 1);
|
|
97
|
-
|
|
98
|
-
// Try to parse as number if possible
|
|
99
|
-
const numValue = Number(value);
|
|
100
|
-
metadata[key] = isNaN(numValue) ? value : numValue;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return Object.keys(metadata).length > 0 ? metadata : undefined;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { ApiPropertyOptional } from '@nestjs/swagger';
|
|
2
|
-
import { IsOptional, IsObject } from 'class-validator';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Query parameters for creating a dismissible item.
|
|
6
|
-
*/
|
|
7
|
-
export class CreateDismissibleItemQueryDto {
|
|
8
|
-
@ApiPropertyOptional({
|
|
9
|
-
description: 'Optional metadata to attach to the item',
|
|
10
|
-
example: { key: 'value' },
|
|
11
|
-
type: 'object',
|
|
12
|
-
additionalProperties: true,
|
|
13
|
-
})
|
|
14
|
-
@IsOptional()
|
|
15
|
-
@IsObject()
|
|
16
|
-
metadata?: Record<string, string | number>;
|
|
17
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { SuccessResponseDto } from '../../../response/dtos/success-response.dto';
|
|
2
|
-
import { DismissibleItemResponseDto } from '../../dismissible-item-response.dto';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Response DTO for the getOrCreate operation.
|
|
6
|
-
*/
|
|
7
|
-
export class GetOrCreateResponseDto extends SuccessResponseDto(DismissibleItemResponseDto) {}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { mock } from 'ts-jest-mocker';
|
|
2
|
-
import { RestoreController } from './restore.controller';
|
|
3
|
-
import { DismissibleService } from '../../../core/dismissible.service';
|
|
4
|
-
import { DismissibleItemMapper } from '../../dismissible-item.mapper';
|
|
5
|
-
import { BaseMetadata } from '@dismissible/nestjs-dismissible-item';
|
|
6
|
-
import { createTestItem, createTestContext } from '../../../testing/factories';
|
|
7
|
-
import { ResponseService } from '../../../response';
|
|
8
|
-
|
|
9
|
-
describe('RestoreController', () => {
|
|
10
|
-
let controller: RestoreController;
|
|
11
|
-
let mockService: jest.Mocked<DismissibleService<BaseMetadata>>;
|
|
12
|
-
let mockResponseService: jest.Mocked<ResponseService>;
|
|
13
|
-
let mapper: DismissibleItemMapper;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
mockService = mock(DismissibleService);
|
|
17
|
-
mockResponseService = mock(ResponseService, { failIfMockNotProvided: false });
|
|
18
|
-
mockResponseService.success.mockImplementation((data) => ({ data }));
|
|
19
|
-
mapper = new DismissibleItemMapper();
|
|
20
|
-
|
|
21
|
-
controller = new RestoreController(mockService, mapper, mockResponseService);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe('restore', () => {
|
|
25
|
-
it('should return restored item wrapped in data', async () => {
|
|
26
|
-
const item = createTestItem({ id: 'test-item' });
|
|
27
|
-
const previousItem = createTestItem({
|
|
28
|
-
id: 'test-item',
|
|
29
|
-
dismissedAt: new Date(),
|
|
30
|
-
});
|
|
31
|
-
const context = createTestContext();
|
|
32
|
-
|
|
33
|
-
mockService.restore.mockResolvedValue({ item, previousItem });
|
|
34
|
-
|
|
35
|
-
const result = await controller.restore('test-user-id', 'test-item', context);
|
|
36
|
-
|
|
37
|
-
expect(result.data.itemId).toBe('test-item');
|
|
38
|
-
expect(mockService.restore).toHaveBeenCalledWith('test-item', 'test-user-id', context);
|
|
39
|
-
expect(mockResponseService.success).toHaveBeenCalled();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
});
|