@gvrs/nestjs-hcaptcha 0.1.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +21 -0
  3. package/README.md +133 -0
  4. package/index.cjs.d.ts +1 -0
  5. package/index.cjs.default.js +1 -0
  6. package/index.cjs.js +28 -0
  7. package/index.cjs.mjs +2 -0
  8. package/index.esm.js +6 -0
  9. package/lib/get-captcha-data/get-captcha-data.cjs.js +18 -0
  10. package/lib/get-captcha-data/get-captcha-data.esm.js +14 -0
  11. package/lib/hcaptcha.exception.cjs.js +15 -0
  12. package/lib/hcaptcha.exception.esm.js +11 -0
  13. package/lib/hcaptcha.guard.cjs.js +33 -0
  14. package/lib/hcaptcha.guard.esm.js +29 -0
  15. package/lib/hcaptcha.module.cjs.js +39 -0
  16. package/lib/hcaptcha.module.esm.js +35 -0
  17. package/lib/hcaptcha.service.cjs.js +40 -0
  18. package/lib/hcaptcha.service.esm.js +36 -0
  19. package/lib/options/hcaptcha-options.module.cjs.js +40 -0
  20. package/lib/options/hcaptcha-options.module.esm.js +35 -0
  21. package/lib/verify-captcha.decorator.cjs.js +10 -0
  22. package/lib/verify-captcha.decorator.esm.js +6 -0
  23. package/package.json +76 -0
  24. package/src/index.d.ts +1 -0
  25. package/src/lib/get-captcha-data/get-captcha-data.d.ts +7 -0
  26. package/src/lib/get-captcha-data/index.d.ts +1 -0
  27. package/src/lib/hcaptcha.exception.d.ts +4 -0
  28. package/src/lib/hcaptcha.guard.d.ts +9 -0
  29. package/src/lib/hcaptcha.module.d.ts +6 -0
  30. package/src/lib/hcaptcha.service.d.ts +6 -0
  31. package/src/lib/index.d.ts +8 -0
  32. package/src/lib/options/hcaptcha-options.module.d.ts +7 -0
  33. package/src/lib/options/hcaptcha-options.types.d.ts +7 -0
  34. package/src/lib/options/index.d.ts +2 -0
  35. package/src/lib/typings.d.ts +2 -0
  36. package/src/lib/verify-captcha.decorator.d.ts +1 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver).
4
+
5
+ ## 0.1.0 (2024-01-28)
6
+
7
+
8
+ ### Features
9
+
10
+ * initial commit ([9008bc3](https://github.com/alexgavrusev/nestjs-hcaptcha/commit/9008bc3386fc8dad738af6c5a96ed28424812f63))
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Aliaksandr Haurusiou
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.
package/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # @gvrs/nestjs-hcaptcha
2
+
3
+ A NestJS module for adding hCaptcha validation
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm i @gvrs/nestjs-hcaptcha
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ First, provide the options in the root `AppModule`:
14
+
15
+ ```ts
16
+ @Module({
17
+ imports: [
18
+ HcaptchaModule.forRoot({
19
+ secret: 'YOUR_HCAPTCHA_SECRET',
20
+ }),
21
+ ],
22
+ })
23
+ export class AppModule {}
24
+ ```
25
+
26
+ Afterward, import the `HcaptchaModule` in the module where you need to use captcha validation:
27
+
28
+ ```ts
29
+ @Module({
30
+ imports: [HcaptchaModule],
31
+ controllers: [UsersController],
32
+ })
33
+ export class UsersModule {}
34
+ ```
35
+
36
+ Finally, decorate the controller method with `@VerifyCaptcha()`:
37
+
38
+ ```ts
39
+ @Controller('users')
40
+ class UsersController {
41
+ @Post('register')
42
+ @VerifyCaptcha()
43
+ register() {}
44
+ }
45
+ ```
46
+
47
+ By default, the hCaptcha token will be extracted from the `h-captcha-response` request body field
48
+
49
+ ### Setting the sitekey you expect to see
50
+
51
+ Provide the `sitekey` option in the root `HcaptchaModule`:
52
+
53
+ ```ts
54
+ @Module({
55
+ imports: [
56
+ HcaptchaModule.forRoot({
57
+ secret: 'YOUR_HCAPTCHA_SECRET',
58
+ sitekey: 'YOUR_SITEKEY',
59
+ }),
60
+ ],
61
+ })
62
+ export class AppModule {}
63
+ ```
64
+
65
+ ### Customizing the captcha data extraction
66
+
67
+ If you want to customize the retrieval of the hCaptcha token and/or the user's IP address, provide an implementation of `getCaptchaData` in the root `HcaptchaModule`:
68
+
69
+ ```ts
70
+ @Module({
71
+ imports: [
72
+ HcaptchaModule.forRoot({
73
+ secret: 'YOUR_HCAPTCHA_SECRET',
74
+ getCaptchaData: (ctx) => {
75
+ const request = ctx.switchToHttp().getRequest();
76
+
77
+ const token = request.body['token'];
78
+ const remoteip = request.headers['x-forwarded-for'];
79
+
80
+ return { token, remoteip };
81
+ },
82
+ }),
83
+ ],
84
+ })
85
+ export class AppModule {}
86
+ ```
87
+
88
+ ### Customizing the error response
89
+
90
+ By default, when the captcha is invalid, or cannot be validated, a 403 error will be sent to the client. To customize that response, use an [exception filter](https://docs.nestjs.com/exception-filters):
91
+
92
+ ```ts
93
+ @Catch(HcaptchaException)
94
+ class HcaptchaExceptionFilter implements ExceptionFilter {
95
+ catch(exception: HcaptchaException, host: ArgumentsHost) {
96
+ const ctx = host.switchToHttp();
97
+ const response = ctx.getResponse();
98
+ const status = 400;
99
+
100
+ response.status(status).json({
101
+ statusCode: status,
102
+ message: 'Invalid captcha',
103
+ });
104
+ }
105
+ }
106
+ ```
107
+
108
+ ### Imperative captcha verification
109
+
110
+ If you don't want to, or cannot use the `@VerifyCaptha()` decorator or the `HcaptchaGuard`, you can verify the captcha by using the `HcaptchaService`:
111
+
112
+ ```ts
113
+ @Controller('users')
114
+ class UsersController {
115
+ constructor(private readonly hcaptchaService: HcaptchaService) {}
116
+
117
+ @Post('register')
118
+ async register(@Req() request: Request) {
119
+ try {
120
+ const token = request.body['h-captcha-response'];
121
+
122
+ // returns the hCaptcha JSON response, or throws a HcaptchaException
123
+ const verifyResponse = await this.hcaptchaService.verifyCaptcha(token);
124
+ } catch {
125
+ throw new BadRequestException();
126
+ }
127
+ }
128
+ }
129
+ ```
130
+
131
+ ## License
132
+
133
+ MIT © Aliaksandr Haurusiou.
package/index.cjs.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/index";
@@ -0,0 +1 @@
1
+ exports._default = require('./index.cjs.js').default;
package/index.cjs.js ADDED
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var getCaptchaData = require('./lib/get-captcha-data/get-captcha-data.cjs.js');
6
+ var hcaptcha_exception = require('./lib/hcaptcha.exception.cjs.js');
7
+ var hcaptcha_guard = require('./lib/hcaptcha.guard.cjs.js');
8
+ var hcaptcha_module = require('./lib/hcaptcha.module.cjs.js');
9
+ var hcaptcha_service = require('./lib/hcaptcha.service.cjs.js');
10
+ var verifyCaptcha_decorator = require('./lib/verify-captcha.decorator.cjs.js');
11
+
12
+
13
+
14
+ exports.defaultGetCaptchaData = getCaptchaData.defaultGetCaptchaData;
15
+ exports.HcaptchaException = hcaptcha_exception.HcaptchaException;
16
+ Object.defineProperty(exports, 'HcaptchaGuard', {
17
+ enumerable: true,
18
+ get: function () { return hcaptcha_guard.HcaptchaGuard; }
19
+ });
20
+ Object.defineProperty(exports, 'HcaptchaModule', {
21
+ enumerable: true,
22
+ get: function () { return hcaptcha_module.HcaptchaModule; }
23
+ });
24
+ Object.defineProperty(exports, 'HcaptchaService', {
25
+ enumerable: true,
26
+ get: function () { return hcaptcha_service.HcaptchaService; }
27
+ });
28
+ exports.VerifyCaptcha = verifyCaptcha_decorator.VerifyCaptcha;
package/index.cjs.mjs ADDED
@@ -0,0 +1,2 @@
1
+ export * from './index.cjs.js';
2
+ export { _default as default } from './index.cjs.default.js';
package/index.esm.js ADDED
@@ -0,0 +1,6 @@
1
+ export { defaultGetCaptchaData } from './lib/get-captcha-data/get-captcha-data.esm.js';
2
+ export { HcaptchaException } from './lib/hcaptcha.exception.esm.js';
3
+ export { HcaptchaGuard } from './lib/hcaptcha.guard.esm.js';
4
+ export { HcaptchaModule } from './lib/hcaptcha.module.esm.js';
5
+ export { HcaptchaService } from './lib/hcaptcha.service.esm.js';
6
+ export { VerifyCaptcha } from './lib/verify-captcha.decorator.esm.js';
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var hcaptcha_exception = require('../hcaptcha.exception.cjs.js');
6
+
7
+ const defaultGetCaptchaData = (context)=>{
8
+ const request = context.switchToHttp().getRequest();
9
+ const token = request.body['h-captcha-response'];
10
+ if (!token) {
11
+ throw new hcaptcha_exception.HcaptchaException(new Error('No hCaptcha token present in request body'));
12
+ }
13
+ return {
14
+ token
15
+ };
16
+ };
17
+
18
+ exports.defaultGetCaptchaData = defaultGetCaptchaData;
@@ -0,0 +1,14 @@
1
+ import { HcaptchaException } from '../hcaptcha.exception.esm.js';
2
+
3
+ const defaultGetCaptchaData = (context)=>{
4
+ const request = context.switchToHttp().getRequest();
5
+ const token = request.body['h-captcha-response'];
6
+ if (!token) {
7
+ throw new HcaptchaException(new Error('No hCaptcha token present in request body'));
8
+ }
9
+ return {
10
+ token
11
+ };
12
+ };
13
+
14
+ export { defaultGetCaptchaData };
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var common = require('@nestjs/common');
6
+
7
+ class HcaptchaException extends common.ForbiddenException {
8
+ constructor(cause, message = 'Forbidden'){
9
+ super(message, {
10
+ cause
11
+ });
12
+ }
13
+ }
14
+
15
+ exports.HcaptchaException = HcaptchaException;
@@ -0,0 +1,11 @@
1
+ import { ForbiddenException } from '@nestjs/common';
2
+
3
+ class HcaptchaException extends ForbiddenException {
4
+ constructor(cause, message = 'Forbidden'){
5
+ super(message, {
6
+ cause
7
+ });
8
+ }
9
+ }
10
+
11
+ export { HcaptchaException };
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _ts_decorate = require('@swc/helpers/_/_ts_decorate');
6
+ var _ts_metadata = require('@swc/helpers/_/_ts_metadata');
7
+ var _ts_param = require('@swc/helpers/_/_ts_param');
8
+ var common = require('@nestjs/common');
9
+ var hcaptchaOptions_module = require('./options/hcaptcha-options.module.cjs.js');
10
+ var hcaptcha_service = require('./hcaptcha.service.cjs.js');
11
+
12
+ class HcaptchaGuard {
13
+ async canActivate(context) {
14
+ const { token, remoteip } = this.options.getCaptchaData(context);
15
+ await this.hcaptchaService.verifyCaptcha(token, remoteip);
16
+ return true;
17
+ }
18
+ constructor(options, hcaptchaService){
19
+ this.options = options;
20
+ this.hcaptchaService = hcaptchaService;
21
+ }
22
+ }
23
+ HcaptchaGuard = _ts_decorate._([
24
+ common.Injectable(),
25
+ _ts_param._(0, common.Inject(hcaptchaOptions_module.NORMALIZED_HCAPTCHA_OPTIONS)),
26
+ _ts_metadata._("design:type", Function),
27
+ _ts_metadata._("design:paramtypes", [
28
+ typeof NormalizedHcaptchaOptions === "undefined" ? Object : NormalizedHcaptchaOptions,
29
+ typeof hcaptcha_service.HcaptchaService === "undefined" ? Object : hcaptcha_service.HcaptchaService
30
+ ])
31
+ ], HcaptchaGuard);
32
+
33
+ exports.HcaptchaGuard = HcaptchaGuard;
@@ -0,0 +1,29 @@
1
+ import { _ } from '@swc/helpers/_/_ts_decorate';
2
+ import { _ as _$2 } from '@swc/helpers/_/_ts_metadata';
3
+ import { _ as _$1 } from '@swc/helpers/_/_ts_param';
4
+ import { Injectable, Inject } from '@nestjs/common';
5
+ import { HcaptchaService } from './hcaptcha.service.esm.js';
6
+ import { NORMALIZED_HCAPTCHA_OPTIONS } from './options/hcaptcha-options.module.esm.js';
7
+
8
+ class HcaptchaGuard {
9
+ async canActivate(context) {
10
+ const { token, remoteip } = this.options.getCaptchaData(context);
11
+ await this.hcaptchaService.verifyCaptcha(token, remoteip);
12
+ return true;
13
+ }
14
+ constructor(options, hcaptchaService){
15
+ this.options = options;
16
+ this.hcaptchaService = hcaptchaService;
17
+ }
18
+ }
19
+ HcaptchaGuard = _([
20
+ Injectable(),
21
+ _$1(0, Inject(NORMALIZED_HCAPTCHA_OPTIONS)),
22
+ _$2("design:type", Function),
23
+ _$2("design:paramtypes", [
24
+ typeof NormalizedHcaptchaOptions === "undefined" ? Object : NormalizedHcaptchaOptions,
25
+ typeof HcaptchaService === "undefined" ? Object : HcaptchaService
26
+ ])
27
+ ], HcaptchaGuard);
28
+
29
+ export { HcaptchaGuard };
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _ts_decorate = require('@swc/helpers/_/_ts_decorate');
6
+ var common = require('@nestjs/common');
7
+ var hcaptchaOptions_module = require('./options/hcaptcha-options.module.cjs.js');
8
+ var hcaptcha_service = require('./hcaptcha.service.cjs.js');
9
+
10
+ class HcaptchaModule {
11
+ static forRoot(options) {
12
+ return {
13
+ module: this,
14
+ imports: [
15
+ hcaptchaOptions_module.HcaptchaOptionsModule.forRoot(options)
16
+ ]
17
+ };
18
+ }
19
+ static forRootAsync(options) {
20
+ return {
21
+ module: this,
22
+ imports: [
23
+ hcaptchaOptions_module.HcaptchaOptionsModule.forRootAsync(options)
24
+ ]
25
+ };
26
+ }
27
+ }
28
+ HcaptchaModule = _ts_decorate._([
29
+ common.Module({
30
+ providers: [
31
+ hcaptcha_service.HcaptchaService
32
+ ],
33
+ exports: [
34
+ hcaptcha_service.HcaptchaService
35
+ ]
36
+ })
37
+ ], HcaptchaModule);
38
+
39
+ exports.HcaptchaModule = HcaptchaModule;
@@ -0,0 +1,35 @@
1
+ import { _ } from '@swc/helpers/_/_ts_decorate';
2
+ import { Module } from '@nestjs/common';
3
+ import { HcaptchaService } from './hcaptcha.service.esm.js';
4
+ import { HcaptchaOptionsModule } from './options/hcaptcha-options.module.esm.js';
5
+
6
+ class HcaptchaModule {
7
+ static forRoot(options) {
8
+ return {
9
+ module: this,
10
+ imports: [
11
+ HcaptchaOptionsModule.forRoot(options)
12
+ ]
13
+ };
14
+ }
15
+ static forRootAsync(options) {
16
+ return {
17
+ module: this,
18
+ imports: [
19
+ HcaptchaOptionsModule.forRootAsync(options)
20
+ ]
21
+ };
22
+ }
23
+ }
24
+ HcaptchaModule = _([
25
+ Module({
26
+ providers: [
27
+ HcaptchaService
28
+ ],
29
+ exports: [
30
+ HcaptchaService
31
+ ]
32
+ })
33
+ ], HcaptchaModule);
34
+
35
+ export { HcaptchaModule };
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _ts_decorate = require('@swc/helpers/_/_ts_decorate');
6
+ var _ts_metadata = require('@swc/helpers/_/_ts_metadata');
7
+ var _ts_param = require('@swc/helpers/_/_ts_param');
8
+ var common = require('@nestjs/common');
9
+ var hcaptcha = require('hcaptcha');
10
+ var hcaptchaOptions_module = require('./options/hcaptcha-options.module.cjs.js');
11
+ var hcaptcha_exception = require('./hcaptcha.exception.cjs.js');
12
+
13
+ class HcaptchaService {
14
+ async verifyCaptcha(token, remoteip) {
15
+ let verifyResponse;
16
+ try {
17
+ verifyResponse = await hcaptcha.verify(this.options.secret, token, remoteip, this.options.sitekey);
18
+ } catch (e) {
19
+ throw new hcaptcha_exception.HcaptchaException(e);
20
+ }
21
+ const { success } = verifyResponse;
22
+ if (!success) {
23
+ throw new hcaptcha_exception.HcaptchaException(verifyResponse);
24
+ }
25
+ return verifyResponse;
26
+ }
27
+ constructor(options){
28
+ this.options = options;
29
+ }
30
+ }
31
+ HcaptchaService = _ts_decorate._([
32
+ common.Injectable(),
33
+ _ts_param._(0, common.Inject(hcaptchaOptions_module.NORMALIZED_HCAPTCHA_OPTIONS)),
34
+ _ts_metadata._("design:type", Function),
35
+ _ts_metadata._("design:paramtypes", [
36
+ typeof NormalizedHcaptchaOptions === "undefined" ? Object : NormalizedHcaptchaOptions
37
+ ])
38
+ ], HcaptchaService);
39
+
40
+ exports.HcaptchaService = HcaptchaService;
@@ -0,0 +1,36 @@
1
+ import { _ } from '@swc/helpers/_/_ts_decorate';
2
+ import { _ as _$2 } from '@swc/helpers/_/_ts_metadata';
3
+ import { _ as _$1 } from '@swc/helpers/_/_ts_param';
4
+ import { Injectable, Inject } from '@nestjs/common';
5
+ import { verify } from 'hcaptcha';
6
+ import { HcaptchaException } from './hcaptcha.exception.esm.js';
7
+ import { NORMALIZED_HCAPTCHA_OPTIONS } from './options/hcaptcha-options.module.esm.js';
8
+
9
+ class HcaptchaService {
10
+ async verifyCaptcha(token, remoteip) {
11
+ let verifyResponse;
12
+ try {
13
+ verifyResponse = await verify(this.options.secret, token, remoteip, this.options.sitekey);
14
+ } catch (e) {
15
+ throw new HcaptchaException(e);
16
+ }
17
+ const { success } = verifyResponse;
18
+ if (!success) {
19
+ throw new HcaptchaException(verifyResponse);
20
+ }
21
+ return verifyResponse;
22
+ }
23
+ constructor(options){
24
+ this.options = options;
25
+ }
26
+ }
27
+ HcaptchaService = _([
28
+ Injectable(),
29
+ _$1(0, Inject(NORMALIZED_HCAPTCHA_OPTIONS)),
30
+ _$2("design:type", Function),
31
+ _$2("design:paramtypes", [
32
+ typeof NormalizedHcaptchaOptions === "undefined" ? Object : NormalizedHcaptchaOptions
33
+ ])
34
+ ], HcaptchaService);
35
+
36
+ export { HcaptchaService };
@@ -0,0 +1,40 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _extends = require('@swc/helpers/_/_extends');
6
+ var _ts_decorate = require('@swc/helpers/_/_ts_decorate');
7
+ var common = require('@nestjs/common');
8
+ var getCaptchaData = require('../get-captcha-data/get-captcha-data.cjs.js');
9
+
10
+ const PROVIDED_HCAPTCHA_OPTIONS = Symbol('PROVIDED_HCAPTCHA_OPTIONS');
11
+ const NORMALIZED_HCAPTCHA_OPTIONS = Symbol('NORMALIZED_HCAPTCHA_OPTIONS');
12
+ const normalizeOptions = (options)=>_extends._({
13
+ getCaptchaData: getCaptchaData.defaultGetCaptchaData
14
+ }, options);
15
+ const { ASYNC_OPTIONS_TYPE: ASYNC_HCAPTCHA_OPTIONS_TYPE, ConfigurableModuleClass } = new common.ConfigurableModuleBuilder({
16
+ optionsInjectionToken: PROVIDED_HCAPTCHA_OPTIONS
17
+ }).setClassMethodName('forRoot').setExtras({}, (def)=>_extends._({}, def, {
18
+ global: true,
19
+ providers: [
20
+ ...def.providers,
21
+ {
22
+ provide: NORMALIZED_HCAPTCHA_OPTIONS,
23
+ useFactory: normalizeOptions,
24
+ inject: [
25
+ PROVIDED_HCAPTCHA_OPTIONS
26
+ ]
27
+ }
28
+ ],
29
+ exports: [
30
+ NORMALIZED_HCAPTCHA_OPTIONS
31
+ ]
32
+ })).build();
33
+ class HcaptchaOptionsModule extends ConfigurableModuleClass {
34
+ }
35
+ HcaptchaOptionsModule = _ts_decorate._([
36
+ common.Module({})
37
+ ], HcaptchaOptionsModule);
38
+
39
+ exports.HcaptchaOptionsModule = HcaptchaOptionsModule;
40
+ exports.NORMALIZED_HCAPTCHA_OPTIONS = NORMALIZED_HCAPTCHA_OPTIONS;
@@ -0,0 +1,35 @@
1
+ import { _ } from '@swc/helpers/_/_extends';
2
+ import { _ as _$1 } from '@swc/helpers/_/_ts_decorate';
3
+ import { ConfigurableModuleBuilder, Module } from '@nestjs/common';
4
+ import { defaultGetCaptchaData } from '../get-captcha-data/get-captcha-data.esm.js';
5
+
6
+ const PROVIDED_HCAPTCHA_OPTIONS = Symbol('PROVIDED_HCAPTCHA_OPTIONS');
7
+ const NORMALIZED_HCAPTCHA_OPTIONS = Symbol('NORMALIZED_HCAPTCHA_OPTIONS');
8
+ const normalizeOptions = (options)=>_({
9
+ getCaptchaData: defaultGetCaptchaData
10
+ }, options);
11
+ const { ASYNC_OPTIONS_TYPE: ASYNC_HCAPTCHA_OPTIONS_TYPE, ConfigurableModuleClass } = new ConfigurableModuleBuilder({
12
+ optionsInjectionToken: PROVIDED_HCAPTCHA_OPTIONS
13
+ }).setClassMethodName('forRoot').setExtras({}, (def)=>_({}, def, {
14
+ global: true,
15
+ providers: [
16
+ ...def.providers,
17
+ {
18
+ provide: NORMALIZED_HCAPTCHA_OPTIONS,
19
+ useFactory: normalizeOptions,
20
+ inject: [
21
+ PROVIDED_HCAPTCHA_OPTIONS
22
+ ]
23
+ }
24
+ ],
25
+ exports: [
26
+ NORMALIZED_HCAPTCHA_OPTIONS
27
+ ]
28
+ })).build();
29
+ class HcaptchaOptionsModule extends ConfigurableModuleClass {
30
+ }
31
+ HcaptchaOptionsModule = _$1([
32
+ Module({})
33
+ ], HcaptchaOptionsModule);
34
+
35
+ export { HcaptchaOptionsModule, NORMALIZED_HCAPTCHA_OPTIONS };
@@ -0,0 +1,10 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var common = require('@nestjs/common');
6
+ var hcaptcha_guard = require('./hcaptcha.guard.cjs.js');
7
+
8
+ const VerifyCaptcha = ()=>common.applyDecorators(common.UseGuards(hcaptcha_guard.HcaptchaGuard));
9
+
10
+ exports.VerifyCaptcha = VerifyCaptcha;
@@ -0,0 +1,6 @@
1
+ import { applyDecorators, UseGuards } from '@nestjs/common';
2
+ import { HcaptchaGuard } from './hcaptcha.guard.esm.js';
3
+
4
+ const VerifyCaptcha = ()=>applyDecorators(UseGuards(HcaptchaGuard));
5
+
6
+ export { VerifyCaptcha };
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@gvrs/nestjs-hcaptcha",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "author": "Alex Gavrusev <alex@gavrusev.dev>",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/alexgavrusev/nestjs-hcaptcha.git"
9
+ },
10
+ "homepage": "https://github.com/alexgavrusev/nestjs-hcaptcha#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/alexgavrusev/nestjs-hcaptcha/issues"
13
+ },
14
+ "scripts": {
15
+ "prepare": "node -e \"if(require('fs').existsSync('.git')){/* proceed only if .git is found */ process.exit(1)}\" || is-ci || husky install"
16
+ },
17
+ "dependencies": {
18
+ "@swc/helpers": "~0.5.2"
19
+ },
20
+ "devDependencies": {
21
+ "@commitlint/cli": "^18.0.0",
22
+ "@commitlint/config-conventional": "^18.0.0",
23
+ "@gvrs-nx/ts-package": "0.3.0",
24
+ "@jscutlery/semver": "^4.1.0",
25
+ "@nestjs/common": "10.3.0",
26
+ "@nestjs/platform-express": "10.3.0",
27
+ "@nestjs/testing": "10.3.0",
28
+ "@nx/eslint": "17.2.8",
29
+ "@nx/eslint-plugin": "17.2.8",
30
+ "@nx/js": "17.2.8",
31
+ "@nx/rollup": "17.2.8",
32
+ "@nx/vite": "17.2.8",
33
+ "@nx/workspace": "17.2.8",
34
+ "@swc-node/register": "~1.6.7",
35
+ "@swc/cli": "~0.1.62",
36
+ "@swc/core": "~1.3.85",
37
+ "@types/express": "4.17.21",
38
+ "@types/node": "18.7.1",
39
+ "@types/supertest": "6.0.2",
40
+ "@typescript-eslint/eslint-plugin": "^6.9.1",
41
+ "@typescript-eslint/parser": "^6.9.1",
42
+ "@vitest/coverage-v8": "~0.34.6",
43
+ "@vitest/ui": "~0.34.6",
44
+ "eslint": "~8.48.0",
45
+ "eslint-config-prettier": "^9.0.0",
46
+ "hcaptcha": "0.1.1",
47
+ "husky": "^8.0.0",
48
+ "is-ci": "^3.0.0",
49
+ "nock": "13.5.0",
50
+ "nx": "17.2.8",
51
+ "prettier": "^2.6.2",
52
+ "supertest": "6.3.4",
53
+ "tslib": "^2.3.0",
54
+ "typescript": "~5.2.2",
55
+ "unplugin-swc": "1.4.4",
56
+ "verdaccio": "^5.0.4",
57
+ "vite": "^5.0.0",
58
+ "vitest": "1.2.1",
59
+ "vitest-mock-extended": "1.3.1"
60
+ },
61
+ "peerDependencies": {
62
+ "@nestjs/common": "^10.0.0",
63
+ "hcaptcha": "~0.1.1"
64
+ },
65
+ "sideEffects": false,
66
+ "exports": {
67
+ "./package.json": "./package.json",
68
+ ".": {
69
+ "module": "./index.esm.js",
70
+ "import": "./index.cjs.mjs",
71
+ "default": "./index.cjs.js"
72
+ }
73
+ },
74
+ "module": "./index.esm.js",
75
+ "main": "./index.cjs.js"
76
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './lib';
@@ -0,0 +1,7 @@
1
+ import { ExecutionContext } from '@nestjs/common';
2
+ export type CaptchaData = {
3
+ token: string;
4
+ remoteip?: string;
5
+ };
6
+ export type GetCaptchaData = (executionContext: ExecutionContext) => CaptchaData;
7
+ export declare const defaultGetCaptchaData: GetCaptchaData;
@@ -0,0 +1 @@
1
+ export * from './get-captcha-data';
@@ -0,0 +1,4 @@
1
+ import { ForbiddenException } from '@nestjs/common';
2
+ export declare class HcaptchaException extends ForbiddenException {
3
+ constructor(cause: unknown, message?: string);
4
+ }
@@ -0,0 +1,9 @@
1
+ import { CanActivate, ExecutionContext } from '@nestjs/common';
2
+ import type { NormalizedHcaptchaOptions } from './options';
3
+ import { HcaptchaService } from './hcaptcha.service';
4
+ export declare class HcaptchaGuard implements CanActivate {
5
+ private readonly options;
6
+ private readonly hcaptchaService;
7
+ constructor(options: NormalizedHcaptchaOptions, hcaptchaService: HcaptchaService);
8
+ canActivate(context: ExecutionContext): Promise<boolean>;
9
+ }
@@ -0,0 +1,6 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { HcaptchaOptions, AsyncHcaptchaOptions } from './options';
3
+ export declare class HcaptchaModule {
4
+ static forRoot(options: HcaptchaOptions): DynamicModule;
5
+ static forRootAsync(options: AsyncHcaptchaOptions): DynamicModule;
6
+ }
@@ -0,0 +1,6 @@
1
+ import type { NormalizedHcaptchaOptions } from './options';
2
+ export declare class HcaptchaService {
3
+ private readonly options;
4
+ constructor(options: NormalizedHcaptchaOptions);
5
+ verifyCaptcha(token: string, remoteip?: string): Promise<globalThis.VerifyResponse>;
6
+ }
@@ -0,0 +1,8 @@
1
+ export * from './get-captcha-data';
2
+ export type { HcaptchaOptions, AsyncHcaptchaOptions } from './options';
3
+ export * from './hcaptcha.exception';
4
+ export * from './hcaptcha.guard';
5
+ export * from './hcaptcha.module';
6
+ export * from './hcaptcha.service';
7
+ export * from './verify-captcha.decorator';
8
+ export * from './typings';
@@ -0,0 +1,7 @@
1
+ import { HcaptchaOptions } from './hcaptcha-options.types';
2
+ declare const NORMALIZED_HCAPTCHA_OPTIONS: unique symbol;
3
+ declare const ASYNC_HCAPTCHA_OPTIONS_TYPE: import("@nestjs/common").ConfigurableModuleAsyncOptions<HcaptchaOptions, "create"> & Partial<{}>, ConfigurableModuleClass: import("@nestjs/common").ConfigurableModuleCls<HcaptchaOptions, "forRoot", "create", {}>;
4
+ export declare class HcaptchaOptionsModule extends ConfigurableModuleClass {
5
+ }
6
+ export type AsyncHcaptchaOptions = typeof ASYNC_HCAPTCHA_OPTIONS_TYPE;
7
+ export { NORMALIZED_HCAPTCHA_OPTIONS };
@@ -0,0 +1,7 @@
1
+ import { GetCaptchaData } from '../get-captcha-data';
2
+ export type HcaptchaOptions = {
3
+ secret: string;
4
+ sitekey?: string;
5
+ getCaptchaData?: GetCaptchaData;
6
+ };
7
+ export type NormalizedHcaptchaOptions = Required<Pick<HcaptchaOptions, 'getCaptchaData'>> & HcaptchaOptions;
@@ -0,0 +1,2 @@
1
+ export * from './hcaptcha-options.module';
2
+ export * from './hcaptcha-options.types';
@@ -0,0 +1,2 @@
1
+ import { verify } from 'hcaptcha';
2
+ export type VerifyResponse = Awaited<ReturnType<typeof verify>>;
@@ -0,0 +1 @@
1
+ export declare const VerifyCaptcha: () => <TFunction extends Function, Y>(target: object | TFunction, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;