nesties 1.0.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.
package/.eslintignore ADDED
@@ -0,0 +1,4 @@
1
+ webpack.config.js
2
+ dist/*
3
+ build/*
4
+ *.js
package/.eslintrc.js ADDED
@@ -0,0 +1,25 @@
1
+ module.exports = {
2
+ parser: '@typescript-eslint/parser',
3
+ parserOptions: {
4
+ project: 'tsconfig.json',
5
+ tsconfigRootDir : __dirname,
6
+ sourceType: 'module',
7
+ },
8
+ plugins: ['@typescript-eslint/eslint-plugin'],
9
+ extends: [
10
+ 'plugin:@typescript-eslint/recommended',
11
+ 'plugin:prettier/recommended',
12
+ ],
13
+ root: true,
14
+ env: {
15
+ node: true,
16
+ jest: true,
17
+ },
18
+ ignorePatterns: ['.eslintrc.js'],
19
+ rules: {
20
+ '@typescript-eslint/interface-name-prefix': 'off',
21
+ '@typescript-eslint/explicit-function-return-type': 'off',
22
+ '@typescript-eslint/explicit-module-boundary-types': 'off',
23
+ '@typescript-eslint/no-explicit-any': 'off',
24
+ },
25
+ };
package/.prettierrc ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "singleQuote": true,
3
+ "trailingComma": "all"
4
+ }
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Nanahira
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,250 @@
1
+ # Nesties
2
+
3
+ **Nest.js utilities**
4
+
5
+ Nesties is a utility library for Nest.js applications, designed to simplify and enhance common patterns such as decorators, response structures, and request validation. This library provides a set of utilities to streamline your development workflow and improve code reuse and clarity when working with Nest.js.
6
+
7
+ ## Features
8
+
9
+ - **Decorator Merging**: Merge multiple property, method, class, and parameter decorators.
10
+ - **Predefined API Responses**: Simplified and consistent response structures for APIs.
11
+ - **Data Validation Pipes**: Validation pipe utilities to handle query and body validation effortlessly.
12
+ - **Custom Guards**: Easily implement token-based guards and API header validation.
13
+ - **Pagination and Return DTOs**: DTOs for standard and paginated API responses.
14
+
15
+ ## Installation
16
+
17
+ To install Nesties, use npm or yarn:
18
+
19
+ ```bash
20
+ npm install nesties
21
+ ```
22
+
23
+ or
24
+
25
+ ```bash
26
+ yarn add nesties
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### 1. Merging Decorators
32
+
33
+ Nesties allows you to merge multiple decorators of the same type (property, method, class, or parameter). This is useful when you want to combine the functionality of several decorators into one.
34
+
35
+ - **Property Decorator**
36
+
37
+ ```typescript
38
+ import { MergePropertyDecorators } from 'nesties';
39
+
40
+ const CombinedPropertyDecorator = MergePropertyDecorators([Decorator1, Decorator2]);
41
+ ```
42
+
43
+ - **Method Decorator**
44
+
45
+ ```typescript
46
+ import { MergeMethodDecorators } from 'nesties';
47
+
48
+ const CombinedMethodDecorator = MergeMethodDecorators([Decorator1, Decorator2]);
49
+ ```
50
+
51
+ - **Class Decorator**
52
+
53
+ ```typescript
54
+ import { MergeClassDecorators } from 'nesties';
55
+
56
+ const CombinedClassDecorator = MergeClassDecorators([Decorator1, Decorator2]);
57
+ ```
58
+
59
+ - **Parameter Decorator**
60
+
61
+ ```typescript
62
+ import { MergeParameterDecorators } from 'nesties';
63
+
64
+ const CombinedParameterDecorator = MergeParameterDecorators([Decorator1, Decorator2]);
65
+ ```
66
+
67
+ ### 2. API Response Decorators
68
+
69
+ Nesties includes a utility for defining API error responses conveniently.
70
+
71
+ ```typescript
72
+ import { ApiError } from 'nesties';
73
+
74
+ @ApiError(401, 'Unauthorized access')
75
+ ```
76
+
77
+ ### 3. Validation Pipes
78
+
79
+ Nesties provides utilities for creating validation pipes with automatic data transformation and validation.
80
+
81
+ - **Data Pipe**
82
+
83
+ ```typescript
84
+ import { DataPipe } from 'nesties';
85
+
86
+ const validationPipe = DataPipe();
87
+ ```
88
+
89
+ - **Decorators for Request Validation**
90
+
91
+ ```typescript
92
+ import { DataQuery, DataBody } from 'nesties';
93
+
94
+ class ExampleController {
95
+ myMethod(@DataQuery() query: MyQueryDto, @DataBody() body: MyBodyDto) {
96
+ // ...
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## Usage
102
+
103
+ ### 4. Return Message DTOs
104
+
105
+ Nesties provides a set of DTOs for consistent API response structures, and it also includes a utility function `ReturnMessageDto` to generate DTOs dynamically based on the provided class type.
106
+
107
+ - **BlankReturnMessageDto**: A basic structure for returning status and message information.
108
+ - **GenericReturnMessageDto**: A generic version for responses that include data.
109
+ - **PaginatedReturnMessageDto**: For paginated responses, including metadata about pagination.
110
+ - **ReturnMessageDto**: A utility function for generating DTOs based on a class type.
111
+
112
+ ```typescript
113
+ import { BlankReturnMessageDto, GenericReturnMessageDto, PaginatedReturnMessageDto, ReturnMessageDto } from 'nesties';
114
+
115
+ const response = new GenericReturnMessageDto(200, 'Operation successful', myData);
116
+ ```
117
+
118
+ #### Example Usage of `ReturnMessageDto`
119
+
120
+ `ReturnMessageDto` allows you to generate a DTO dynamically based on the structure of a provided class. This is useful when you want to create a standardized response that includes custom data types.
121
+
122
+ Suppose we have a `User` class:
123
+
124
+ ```typescript
125
+ import { ApiProperty } from '@nestjs/swagger';
126
+
127
+ class User {
128
+ @ApiProperty({ description: 'The unique ID of the user', type: Number })
129
+ id: number;
130
+
131
+ @ApiProperty({ description: 'The name of the user', type: String })
132
+ name: string;
133
+
134
+ @ApiProperty({ description: 'The email address of the user', type: String })
135
+ email: string;
136
+ }
137
+ ```
138
+
139
+ You can create a return message DTO for this class:
140
+
141
+ ```typescript
142
+ import { ReturnMessageDto } from 'nesties';
143
+
144
+ class UserReturnMessageDto extends ReturnMessageDto(User) {}
145
+
146
+ const response = new UserReturnMessageDto(200, 'Success', { id: 1, name: 'John Doe', email: 'john.doe@example.com' });
147
+ ```
148
+
149
+ This approach automatically creates a DTO structure with the properties of `User` integrated as the data field, ensuring consistency and reusability in your API responses.
150
+
151
+
152
+ ```
153
+
154
+ ### 5. Token Guard
155
+
156
+ Nesties includes a `TokenGuard` class that validates server tokens from the request headers. This can be used with the `RequireToken` decorator for routes requiring token validation.
157
+
158
+ ```typescript
159
+ import { RequireToken } from 'nesties';
160
+
161
+ @Controller('secure')
162
+ export class SecureController {
163
+ @Get()
164
+ @RequireToken()
165
+ secureEndpoint() {
166
+ // This endpoint requires a token
167
+ }
168
+ }
169
+ ```
170
+
171
+ #### How to Use `TokenGuard`
172
+
173
+ 1. **Set the `SERVER_TOKEN` in the Configuration**
174
+
175
+ In your Nest.js configuration, make sure to set up the `SERVER_TOKEN` using the `@nestjs/config` package.
176
+
177
+ ```typescript
178
+ import { ConfigModule } from '@nestjs/config';
179
+
180
+ @Module({
181
+ imports: [ConfigModule.forRoot()],
182
+ })
183
+ export class AppModule {}
184
+ ```
185
+
186
+ In your environment file (`.env`), define your token:
187
+
188
+ ```
189
+ SERVER_TOKEN=your-secure-token
190
+ ```
191
+
192
+ 2. **Token Validation with `TokenGuard`**
193
+
194
+ `TokenGuard` checks the request headers for a token called `x-server-token`. If this token matches the one defined in your configuration, the request is allowed to proceed. If the token is missing or incorrect, a `401 Unauthorized` error is thrown.
195
+
196
+ This approach is ideal for simple token-based authentication for APIs. It provides a lightweight method to protect routes without implementing a full OAuth or JWT-based system.
197
+
198
+ 3. **Use `RequireToken` Decorator**
199
+
200
+ Apply the `RequireToken` decorator to your controller methods to enforce token validation:
201
+
202
+ ```typescript
203
+ import { Controller, Get } from '@nestjs/common';
204
+ import { RequireToken } from 'nesties';
205
+
206
+ @Controller('api')
207
+ export class ApiController {
208
+ @Get('protected')
209
+ @RequireToken()
210
+ protectedRoute() {
211
+ return { message: 'This is a protected route' };
212
+ }
213
+ }
214
+ ```
215
+
216
+ In this example, the `protectedRoute` method will only be accessible if the request includes the correct `x-server-token` header.
217
+
218
+ ## DTO Classes
219
+
220
+ - **BlankReturnMessageDto**: A basic DTO for standardized API responses.
221
+ - **BlankPaginatedReturnMessageDto**: A DTO for paginated API responses.
222
+ - **GenericReturnMessageDto**: A generic DTO for returning data of any type.
223
+ - **StringReturnMessageDto**: A simple DTO for string responses.
224
+
225
+ ```typescript
226
+ import { StringReturnMessageDto } from 'nesties';
227
+
228
+ const response = new StringReturnMessageDto(200, 'Success', 'This is a string response');
229
+ ```
230
+
231
+ ## Configuration
232
+
233
+ The `TokenGuard` class uses the `ConfigService` from `@nestjs/config` to access configuration values, such as the `SERVER_TOKEN`. Make sure you have `@nestjs/config` installed and configured in your Nest.js project.
234
+
235
+ ```typescript
236
+ import { ConfigModule } from '@nestjs/config';
237
+
238
+ @Module({
239
+ imports: [ConfigModule.forRoot()],
240
+ })
241
+ export class AppModule {}
242
+ ```
243
+
244
+ ## Contributing
245
+
246
+ Contributions are welcome! Please feel free to submit a pull request or report issues.
247
+
248
+ ## License
249
+
250
+ Nesties is MIT licensed.
@@ -0,0 +1,6 @@
1
+ export * from './src/insert-field';
2
+ export * from './src/merge';
3
+ export * from './src/return-message';
4
+ export * from './src/openapi';
5
+ export * from './src/pipe';
6
+ export * from './src/token.guard';
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./src/insert-field"), exports);
18
+ __exportStar(require("./src/merge"), exports);
19
+ __exportStar(require("./src/return-message"), exports);
20
+ __exportStar(require("./src/openapi"), exports);
21
+ __exportStar(require("./src/pipe"), exports);
22
+ __exportStar(require("./src/token.guard"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAmC;AACnC,8CAA4B;AAC5B,uDAAqC;AACrC,gDAA8B;AAC9B,6CAA2B;AAC3B,oDAAkC"}
@@ -0,0 +1,24 @@
1
+ import { ApiPropertyOptions } from '@nestjs/swagger';
2
+ export type AnyClass = new (...args: any[]) => any;
3
+ export type ClassOrArray = AnyClass | [AnyClass];
4
+ export type ClassType<T> = new (...args: any[]) => T;
5
+ export type TypeFromClass<T> = T extends new (...args: any[]) => infer U ? U : never;
6
+ export type ParamsFromClass<T> = T extends new (...args: infer U) => any ? U : never;
7
+ export type ParseType<IC extends ClassOrArray> = IC extends [infer U] ? TypeFromClass<U>[] : TypeFromClass<IC>;
8
+ export declare function getClassFromClassOrArray(o: ClassOrArray): AnyClass;
9
+ export interface InsertOptions<C extends ClassOrArray = ClassOrArray> {
10
+ type: C;
11
+ options?: ApiPropertyOptions;
12
+ }
13
+ type TypeFromInsertOptions<O extends InsertOptions> = O extends InsertOptions<infer C> ? ParseType<C> | (O extends {
14
+ options: {
15
+ required: true;
16
+ };
17
+ } ? never : undefined) : never;
18
+ type Merge<T, U> = {
19
+ [K in keyof T | keyof U]: K extends keyof T ? T[K] : K extends keyof U ? U[K] : never;
20
+ };
21
+ export declare function InsertField<C extends AnyClass, M extends Record<string, InsertOptions>>(cl: C, map: M, newName?: string): new (...args: ParamsFromClass<C>) => Merge<{
22
+ [F in keyof M]: TypeFromInsertOptions<M[F]>;
23
+ }, TypeFromClass<C>>;
24
+ export {};
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getClassFromClassOrArray = getClassFromClassOrArray;
4
+ exports.InsertField = InsertField;
5
+ const swagger_1 = require("@nestjs/swagger");
6
+ function getClassFromClassOrArray(o) {
7
+ return o instanceof Array ? o[0] : o;
8
+ }
9
+ function InsertField(cl, map, newName) {
10
+ const extendedCl = class extends cl {
11
+ };
12
+ for (const key in map) {
13
+ (0, swagger_1.ApiProperty)({
14
+ type: map[key].type,
15
+ ...(map[key].options || {}),
16
+ })(extendedCl.prototype, key);
17
+ }
18
+ Object.defineProperty(extendedCl, 'name', {
19
+ value: newName || cl.name,
20
+ });
21
+ return extendedCl;
22
+ }
23
+ //# sourceMappingURL=insert-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insert-field.js","sourceRoot":"","sources":["../../src/insert-field.ts"],"names":[],"mappings":";;AAeA,4DAEC;AAsBD,kCAwBC;AA/DD,6CAAkE;AAelE,SAAgB,wBAAwB,CAAC,CAAe;IACtD,OAAO,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAsBD,SAAgB,WAAW,CAIzB,EAAK,EACL,GAAM,EACN,OAAgB;IAOhB,MAAM,UAAU,GAAG,KAAM,SAAQ,EAAE;KAAG,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAA,qBAAW,EAAC;YACV,IAAI,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI;YACnB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC;SAC5B,CAAC,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE;QACxC,KAAK,EAAE,OAAO,IAAI,EAAE,CAAC,IAAI;KAC1B,CAAC,CAAC;IACH,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function MergePropertyDecorators(decs: PropertyDecorator[]): PropertyDecorator;
2
+ export declare function MergeMethodDecorators(decs: MethodDecorator[]): MethodDecorator;
3
+ export declare function MergeClassDecorators(decs: ClassDecorator[]): ClassDecorator;
4
+ export declare function MergeParameterDecorators(decs: ParameterDecorator[]): ParameterDecorator;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MergePropertyDecorators = MergePropertyDecorators;
4
+ exports.MergeMethodDecorators = MergeMethodDecorators;
5
+ exports.MergeClassDecorators = MergeClassDecorators;
6
+ exports.MergeParameterDecorators = MergeParameterDecorators;
7
+ function MergePropertyDecorators(decs) {
8
+ return (obj, key) => {
9
+ for (const dec of decs) {
10
+ dec(obj, key);
11
+ }
12
+ };
13
+ }
14
+ function MergeMethodDecorators(decs) {
15
+ return (obj, key, descriptor) => {
16
+ for (const dec of decs) {
17
+ dec(obj, key, descriptor);
18
+ }
19
+ };
20
+ }
21
+ function MergeClassDecorators(decs) {
22
+ return (obj) => {
23
+ for (const dec of decs) {
24
+ dec(obj);
25
+ }
26
+ };
27
+ }
28
+ function MergeParameterDecorators(decs) {
29
+ return (obj, key, index) => {
30
+ for (const dec of decs) {
31
+ dec(obj, key, index);
32
+ }
33
+ };
34
+ }
35
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/merge.ts"],"names":[],"mappings":";;AAAA,0DAQC;AAED,sDAQC;AAED,oDAMC;AAED,4DAQC;AApCD,SAAgB,uBAAuB,CACrC,IAAyB;IAEzB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAClB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,qBAAqB,CACnC,IAAuB;IAEvB,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,EAAE;QAC9B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,oBAAoB,CAAC,IAAsB;IACzD,OAAO,CAAC,GAAG,EAAE,EAAE;QACb,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,GAAG,CAAC,GAAG,CAAC,CAAC;QACX,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,wBAAwB,CACtC,IAA0B;IAE1B,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QACzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const ApiError: (status: number, description: string) => MethodDecorator & ClassDecorator;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApiError = void 0;
4
+ const return_message_1 = require("./return-message");
5
+ const swagger_1 = require("@nestjs/swagger");
6
+ const ApiError = (status, description) => (0, swagger_1.ApiResponse)({ status, type: return_message_1.BlankReturnMessageDto, description });
7
+ exports.ApiError = ApiError;
8
+ //# sourceMappingURL=openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../src/openapi.ts"],"names":[],"mappings":";;;AAAA,qDAAyD;AACzD,6CAA8C;AAEvC,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,WAAmB,EAAE,EAAE,CAC9D,IAAA,qBAAW,EAAC,EAAE,MAAM,EAAE,IAAI,EAAE,sCAAqB,EAAE,WAAW,EAAE,CAAC,CAAC;AADvD,QAAA,QAAQ,YAC+C"}
@@ -0,0 +1,4 @@
1
+ import { PipeTransform, Type, ValidationPipe } from '@nestjs/common';
2
+ export declare const DataPipe: () => ValidationPipe;
3
+ export declare const DataQuery: (...extraPipes: (Type<PipeTransform> | PipeTransform)[]) => ParameterDecorator;
4
+ export declare const DataBody: (...extraPipes: (Type<PipeTransform> | PipeTransform)[]) => ParameterDecorator;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataBody = exports.DataQuery = exports.DataPipe = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const DataPipe = () => new common_1.ValidationPipe({
6
+ transform: true,
7
+ transformOptions: { enableImplicitConversion: true },
8
+ });
9
+ exports.DataPipe = DataPipe;
10
+ const createDataPipeDec = (nestFieldDec) => (...extraPipes) => nestFieldDec((0, exports.DataPipe)(), ...extraPipes);
11
+ exports.DataQuery = createDataPipeDec(common_1.Query);
12
+ exports.DataBody = createDataPipeDec(common_1.Body);
13
+ //# sourceMappingURL=pipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipe.js","sourceRoot":"","sources":["../../src/pipe.ts"],"names":[],"mappings":";;;AAAA,2CAMwB;AAEjB,MAAM,QAAQ,GAAG,GAAG,EAAE,CAC3B,IAAI,uBAAc,CAAC;IACjB,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,EAAE,wBAAwB,EAAE,IAAI,EAAE;CACrD,CAAC,CAAC;AAJQ,QAAA,QAAQ,YAIhB;AAEL,MAAM,iBAAiB,GACrB,CACE,YAEuB,EACvB,EAAE,CACJ,CAAC,GAAG,UAAmD,EAAE,EAAE,CACzD,YAAY,CAAC,IAAA,gBAAQ,GAAE,EAAE,GAAG,UAAU,CAAC,CAAC;AAE/B,QAAA,SAAS,GAAG,iBAAiB,CAAC,cAAK,CAAC,CAAC;AACrC,QAAA,QAAQ,GAAG,iBAAiB,CAAC,aAAI,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { HttpException } from '@nestjs/common';
2
+ import { AnyClass, ClassOrArray, ParseType } from './insert-field';
3
+ export interface PageSettingsWise {
4
+ pageCount: number;
5
+ recordsPerPage: number;
6
+ }
7
+ export interface BlankReturnMessage {
8
+ statusCode: number;
9
+ message: string;
10
+ success: boolean;
11
+ }
12
+ export interface ReturnMessage<T> extends BlankReturnMessage {
13
+ data?: T;
14
+ }
15
+ export declare class BlankReturnMessageDto implements BlankReturnMessage {
16
+ statusCode: number;
17
+ message: string;
18
+ success: boolean;
19
+ constructor(statusCode: number, message?: string);
20
+ toException(): HttpException;
21
+ }
22
+ export declare class BlankPaginatedReturnMessageDto extends BlankReturnMessageDto implements PageSettingsWise {
23
+ total: number;
24
+ totalPages: number;
25
+ pageCount: number;
26
+ recordsPerPage: number;
27
+ constructor(statusCode: number, message: string, total: number, pageSettings: PageSettingsWise);
28
+ }
29
+ export declare class GenericReturnMessageDto<T> extends BlankReturnMessageDto implements ReturnMessage<T> {
30
+ data?: T;
31
+ constructor(statusCode: number, message?: string, data?: T);
32
+ }
33
+ export declare function ReturnMessageDto<T extends ClassOrArray>(type: T): new (statusCode: number, message: string, data: ParseType<T>) => GenericReturnMessageDto<ParseType<T>>;
34
+ export declare class GenericPaginatedReturnMessageDto<T> extends BlankPaginatedReturnMessageDto implements PageSettingsWise, ReturnMessage<T[]> {
35
+ data: T[];
36
+ constructor(statusCode: number, message: string, data: T[], total: number, pageSettings: PageSettingsWise);
37
+ }
38
+ export declare function PaginatedReturnMessageDto<T extends AnyClass>(type: T): new (statusCode: number, message: string, data: InstanceType<T>[], total: number, pageSettings: PageSettingsWise) => GenericPaginatedReturnMessageDto<InstanceType<T>>;
39
+ export declare class StringReturnMessageDto extends GenericReturnMessageDto<string> {
40
+ data: string;
41
+ }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.StringReturnMessageDto = exports.GenericPaginatedReturnMessageDto = exports.GenericReturnMessageDto = exports.BlankPaginatedReturnMessageDto = exports.BlankReturnMessageDto = void 0;
13
+ exports.ReturnMessageDto = ReturnMessageDto;
14
+ exports.PaginatedReturnMessageDto = PaginatedReturnMessageDto;
15
+ const swagger_1 = require("@nestjs/swagger");
16
+ const common_1 = require("@nestjs/common");
17
+ const insert_field_1 = require("./insert-field");
18
+ class BlankReturnMessageDto {
19
+ constructor(statusCode, message) {
20
+ this.statusCode = statusCode;
21
+ this.message = message || 'success';
22
+ this.success = statusCode < 400;
23
+ }
24
+ toException() {
25
+ return new common_1.HttpException(this, this.statusCode);
26
+ }
27
+ }
28
+ exports.BlankReturnMessageDto = BlankReturnMessageDto;
29
+ __decorate([
30
+ (0, swagger_1.ApiProperty)({ description: 'Return code', type: Number }),
31
+ __metadata("design:type", Number)
32
+ ], BlankReturnMessageDto.prototype, "statusCode", void 0);
33
+ __decorate([
34
+ (0, swagger_1.ApiProperty)({ description: 'Return message', type: String }),
35
+ __metadata("design:type", String)
36
+ ], BlankReturnMessageDto.prototype, "message", void 0);
37
+ __decorate([
38
+ (0, swagger_1.ApiProperty)({ description: 'Whether success.', type: Boolean }),
39
+ __metadata("design:type", Boolean)
40
+ ], BlankReturnMessageDto.prototype, "success", void 0);
41
+ class BlankPaginatedReturnMessageDto extends BlankReturnMessageDto {
42
+ constructor(statusCode, message, total, pageSettings) {
43
+ super(statusCode, message);
44
+ this.total = total;
45
+ this.pageCount = pageSettings.pageCount;
46
+ this.recordsPerPage = pageSettings.recordsPerPage;
47
+ this.totalPages = Math.ceil(total / pageSettings.recordsPerPage);
48
+ }
49
+ }
50
+ exports.BlankPaginatedReturnMessageDto = BlankPaginatedReturnMessageDto;
51
+ __decorate([
52
+ (0, swagger_1.ApiProperty)({ description: 'Total record count.', type: Number }),
53
+ __metadata("design:type", Number)
54
+ ], BlankPaginatedReturnMessageDto.prototype, "total", void 0);
55
+ __decorate([
56
+ (0, swagger_1.ApiProperty)({ description: 'Total page count.', type: Number }),
57
+ __metadata("design:type", Number)
58
+ ], BlankPaginatedReturnMessageDto.prototype, "totalPages", void 0);
59
+ __decorate([
60
+ (0, swagger_1.ApiProperty)({ description: 'Current page.', type: Number }),
61
+ __metadata("design:type", Number)
62
+ ], BlankPaginatedReturnMessageDto.prototype, "pageCount", void 0);
63
+ __decorate([
64
+ (0, swagger_1.ApiProperty)({ description: 'Records per page.', type: Number }),
65
+ __metadata("design:type", Number)
66
+ ], BlankPaginatedReturnMessageDto.prototype, "recordsPerPage", void 0);
67
+ class GenericReturnMessageDto extends BlankReturnMessageDto {
68
+ constructor(statusCode, message, data) {
69
+ super(statusCode, message);
70
+ this.data = data;
71
+ }
72
+ }
73
+ exports.GenericReturnMessageDto = GenericReturnMessageDto;
74
+ function ReturnMessageDto(type) {
75
+ return (0, insert_field_1.InsertField)(GenericReturnMessageDto, {
76
+ data: {
77
+ type,
78
+ options: {
79
+ required: false,
80
+ description: 'Return data.',
81
+ },
82
+ },
83
+ }, `${(0, insert_field_1.getClassFromClassOrArray)(type).name}ReturnMessageDto`);
84
+ }
85
+ class GenericPaginatedReturnMessageDto extends BlankPaginatedReturnMessageDto {
86
+ constructor(statusCode, message, data, total, pageSettings) {
87
+ super(statusCode, message, total, pageSettings);
88
+ this.data = data;
89
+ }
90
+ }
91
+ exports.GenericPaginatedReturnMessageDto = GenericPaginatedReturnMessageDto;
92
+ function PaginatedReturnMessageDto(type) {
93
+ return (0, insert_field_1.InsertField)(GenericPaginatedReturnMessageDto, {
94
+ data: {
95
+ type: [type],
96
+ options: {
97
+ required: false,
98
+ description: 'Return data.',
99
+ },
100
+ },
101
+ }, `${(0, insert_field_1.getClassFromClassOrArray)(type).name}PaginatedReturnMessageDto`);
102
+ }
103
+ class StringReturnMessageDto extends GenericReturnMessageDto {
104
+ }
105
+ exports.StringReturnMessageDto = StringReturnMessageDto;
106
+ __decorate([
107
+ (0, swagger_1.ApiProperty)({ description: 'Return data.', type: String, required: false }),
108
+ __metadata("design:type", String)
109
+ ], StringReturnMessageDto.prototype, "data", void 0);
110
+ //# sourceMappingURL=return-message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"return-message.js","sourceRoot":"","sources":["../../src/return-message.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { CanActivate, ExecutionContext } from '@nestjs/common';
2
+ import { ConfigService } from '@nestjs/config';
3
+ export declare class TokenGuard implements CanActivate {
4
+ private config;
5
+ private token;
6
+ constructor(config: ConfigService);
7
+ canActivate(context: ExecutionContext): Promise<boolean>;
8
+ }
9
+ export declare const RequireToken: () => MethodDecorator;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RequireToken = exports.TokenGuard = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const config_1 = require("@nestjs/config");
15
+ const swagger_1 = require("@nestjs/swagger");
16
+ const return_message_1 = require("./return-message");
17
+ const merge_1 = require("./merge");
18
+ const openapi_1 = require("./openapi");
19
+ let TokenGuard = class TokenGuard {
20
+ constructor(config) {
21
+ this.config = config;
22
+ this.token = this.config.get('SERVER_TOKEN');
23
+ }
24
+ async canActivate(context) {
25
+ const request = context.switchToHttp().getRequest();
26
+ const token = request.headers['x-server-token'];
27
+ if (this.token && token !== this.token) {
28
+ throw new return_message_1.BlankReturnMessageDto(401, 'Unauthorized').toException();
29
+ }
30
+ return true;
31
+ }
32
+ };
33
+ exports.TokenGuard = TokenGuard;
34
+ exports.TokenGuard = TokenGuard = __decorate([
35
+ (0, common_1.Injectable)(),
36
+ __metadata("design:paramtypes", [config_1.ConfigService])
37
+ ], TokenGuard);
38
+ const RequireToken = () => (0, merge_1.MergeMethodDecorators)([
39
+ (0, common_1.UseGuards)(TokenGuard),
40
+ (0, swagger_1.ApiHeader)({
41
+ name: 'x-server-token',
42
+ description: '服务器 token',
43
+ required: false,
44
+ }),
45
+ (0, openapi_1.ApiError)(401, '服务器 Token 不正确'),
46
+ ]);
47
+ exports.RequireToken = RequireToken;
48
+ //# sourceMappingURL=token.guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.guard.js","sourceRoot":"","sources":["../../src/token.guard.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AACxB,2CAA+C;AAC/C,6CAA4C;AAC5C,qDAAyD;AACzD,mCAAgD;AAChD,uCAAqC;AAG9B,IAAM,UAAU,GAAhB,MAAM,UAAU;IAErB,YAAoB,MAAqB;QAArB,WAAM,GAAN,MAAM,CAAe;QADjC,UAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAS,cAAc,CAAC,CAAC;IACZ,CAAC;IAE7C,KAAK,CAAC,WAAW,CAAC,OAAyB;QACzC,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,UAAU,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;YACvC,MAAM,IAAI,sCAAqB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC;QACrE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAA;AAZY,gCAAU;qBAAV,UAAU;IADtB,IAAA,mBAAU,GAAE;qCAGiB,sBAAa;GAF9B,UAAU,CAYtB;AAEM,MAAM,YAAY,GAAG,GAAG,EAAE,CAC/B,IAAA,6BAAqB,EAAC;IACpB,IAAA,kBAAS,EAAC,UAAU,CAAC;IACrB,IAAA,mBAAS,EAAC;QACR,IAAI,EAAE,gBAAgB;QACtB,WAAW,EAAE,WAAW;QACxB,QAAQ,EAAE,KAAK;KAChB,CAAC;IACF,IAAA,kBAAQ,EAAC,GAAG,EAAE,eAAe,CAAC;CAC/B,CAAC,CAAC;AATQ,QAAA,YAAY,gBASpB"}
package/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './src/insert-field';
2
+ export * from './src/merge';
3
+ export * from './src/return-message';
4
+ export * from './src/openapi';
5
+ export * from './src/pipe';
6
+ export * from './src/token.guard';
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "nesties",
3
+ "description": "Nest.js utilities",
4
+ "version": "1.0.1",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "lint": "eslint --fix .",
9
+ "build": "rimraf dist && tsc",
10
+ "test": "jest --passWithNoTests",
11
+ "start": "node dist/index.js"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://code.mycard.moe/3rdeye/nesties.git"
16
+ },
17
+ "author": "Nanahira <nanahira@momobako.com>",
18
+ "license": "MIT",
19
+ "keywords": [],
20
+ "bugs": {
21
+ "url": "https://code.mycard.moe/3rdeye/nesties/issues"
22
+ },
23
+ "homepage": "https://code.mycard.moe/3rdeye/nesties",
24
+ "jest": {
25
+ "moduleFileExtensions": [
26
+ "js",
27
+ "json",
28
+ "ts"
29
+ ],
30
+ "rootDir": "tests",
31
+ "testRegex": ".*\\.spec\\.ts$",
32
+ "transform": {
33
+ "^.+\\.(t|j)s$": "ts-jest"
34
+ },
35
+ "collectCoverageFrom": [
36
+ "**/*.(t|j)s"
37
+ ],
38
+ "coverageDirectory": "../coverage",
39
+ "testEnvironment": "node"
40
+ },
41
+ "devDependencies": {
42
+ "@nestjs/common": "^10.4.6",
43
+ "@nestjs/config": "^3.3.0",
44
+ "@nestjs/swagger": "^7.4.2",
45
+ "@types/jest": "^29.5.14",
46
+ "@types/node": "^22.8.1",
47
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
48
+ "@typescript-eslint/parser": "^6.21.0",
49
+ "eslint": "8.22.0",
50
+ "eslint-config-prettier": "^9.1.0",
51
+ "eslint-plugin-prettier": "^5.2.1",
52
+ "jest": "^29.7.0",
53
+ "prettier": "^3.3.3",
54
+ "rimraf": "^6.0.1",
55
+ "ts-jest": "^29.2.5",
56
+ "typescript": "^5.6.3"
57
+ },
58
+ "peerDependencies": {
59
+ "@nestjs/common": "^9.4.0 || ^10.0.0",
60
+ "@nestjs/swagger": "^7.1.8 || ^6.3.0",
61
+ "@nestjs/config": "^3.0.0"
62
+ }
63
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "outDir": "dist",
4
+ "module": "commonjs",
5
+ "target": "es2021",
6
+ "esModuleInterop": true,
7
+ "emitDecoratorMetadata": true,
8
+ "experimentalDecorators": true,
9
+ "declaration": true,
10
+ "sourceMap": true
11
+ },
12
+ "compileOnSave": true,
13
+ "allowJs": true,
14
+ "include": [
15
+ "*.ts",
16
+ "src/**/*.ts",
17
+ "test/**/*.ts",
18
+ "tests/**/*.ts"
19
+ ]
20
+ }