@captcha-kit/core 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +169 -0
  3. package/dist/Factory/CaptchaFactory.d.ts +16 -0
  4. package/dist/Factory/CaptchaFactory.js +32 -0
  5. package/dist/Factory/index.d.ts +1 -0
  6. package/dist/Factory/index.js +1 -0
  7. package/dist/Function/getCaptchaFormElement.d.ts +8 -0
  8. package/dist/Function/getCaptchaFormElement.js +8 -0
  9. package/dist/Function/getCaptchaScript.d.ts +8 -0
  10. package/dist/Function/getCaptchaScript.js +8 -0
  11. package/dist/Function/index.d.ts +3 -0
  12. package/dist/Function/index.js +3 -0
  13. package/dist/Function/verifyCaptcha.d.ts +9 -0
  14. package/dist/Function/verifyCaptcha.js +9 -0
  15. package/dist/Interface/CaptchaFactoryInterface.d.ts +15 -0
  16. package/dist/Interface/CaptchaFactoryInterface.js +1 -0
  17. package/dist/Interface/CaptchaInterface.d.ts +18 -0
  18. package/dist/Interface/CaptchaInterface.js +1 -0
  19. package/dist/Interface/index.d.ts +2 -0
  20. package/dist/Interface/index.js +2 -0
  21. package/dist/Type/Types.d.ts +3 -0
  22. package/dist/Type/Types.js +1 -0
  23. package/dist/Type/index.d.ts +1 -0
  24. package/dist/Type/index.js +1 -0
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.js +4 -0
  27. package/eslint.config.mjs +6 -0
  28. package/package.json +32 -0
  29. package/src/Factory/CaptchaFactory.ts +44 -0
  30. package/src/Factory/index.ts +1 -0
  31. package/src/Function/getCaptchaFormElement.tsx +11 -0
  32. package/src/Function/getCaptchaScript.tsx +11 -0
  33. package/src/Function/index.tsx +3 -0
  34. package/src/Function/verifyCaptcha.ts +12 -0
  35. package/src/Interface/CaptchaFactoryInterface.ts +17 -0
  36. package/src/Interface/CaptchaInterface.ts +21 -0
  37. package/src/Interface/index.ts +2 -0
  38. package/src/Type/Types.ts +6 -0
  39. package/src/Type/index.ts +1 -0
  40. package/src/index.tsx +4 -0
  41. package/tests/getCaptchaFormElement.test.tsx +25 -0
  42. package/tests/getCaptchaScript.test.tsx +25 -0
  43. package/tests/verifyCaptcha.test.ts +31 -0
  44. package/tsconfig.eslint.json +4 -0
  45. package/tsconfig.json +38 -0
  46. package/vitest.config.ts +9 -0
package/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # MessageKit Core
2
+
3
+ **MessageKit Core is a TypeScript library that provides foundational classes, interfaces, and tools for handling and processing messages within domain-driven and AI applications.** This package offers a set of abstractions that make it easier to manage messaging workflows, including sending and receiving messages across different channels.
4
+
5
+ ## Supported Packages
6
+
7
+ The `@messagekit/core` package supports several email service providers, including:
8
+
9
+ - **Mailgun**: Integration with the Mailgun email service for sending emails.
10
+ - **Nylas**: Integration with the Nylas email service for sending emails.
11
+ - **Resend**: Integration with the Resend email service for sending emails.
12
+ - **SendGrid**: Integration with the SendGrid email service for sending emails.
13
+
14
+ ### Adding New Providers
15
+
16
+ To add a new email provider, you can implement the `EmailProviderFactoryInterface` and `EmailSenderInterface`. Here’s a brief example of how to implement a new provider:
17
+
18
+ 1. **Create a New Folder**: Create a new folder for your provider (e.g., `packages/myprovider`).
19
+ 2. **Implement the Factory**: Create a factory class that implements the `EmailProviderFactoryInterface`. This class should have a method to create an email sender instance.
20
+
21
+ Example:
22
+ ```typescript
23
+ import { MyProviderEmailSender } from './Provider/MyProviderEmailSender';
24
+ import type { TypeMyProviderConfig } from './Type/Types';
25
+ import type { EmailProviderFactoryInterface, EmailSenderInterface } from '@messagekit/core';
26
+
27
+ export class MyProviderEmailProviderFactory implements EmailProviderFactoryInterface<TypeMyProviderConfig> {
28
+ public async createSender(config: TypeMyProviderConfig): Promise<EmailSenderInterface> {
29
+ return new MyProviderEmailSender(config);
30
+ }
31
+ }
32
+ ```
33
+
34
+ 3. **Implement the Email Sender**: Create a class that implements the `EmailSenderInterface`. This class should handle the logic for sending emails.
35
+
36
+ Example:
37
+ ```typescript
38
+ import type { TypeEmailMessage, TypeEmailMessageResponse, EmailSenderInterface } from '@messagekit/core';
39
+
40
+ export class MyProviderEmailSender implements EmailSenderInterface {
41
+ constructor(private config: TypeMyProviderConfig) {}
42
+
43
+ public async send(message: TypeEmailMessage): Promise<TypeEmailMessageResponse> {
44
+ // Implement the logic to send the email using your provider's API
45
+ // It is recommended to use transformers and types for consistency
46
+ }
47
+ }
48
+ ```
49
+
50
+ 4. **Use Transformers and Types**: It is recommended to use transformers and types to ensure consistency in the data being processed. This helps maintain the expected structure and format across different email providers.
51
+
52
+ ### Folder Structure
53
+
54
+ The folder structure for each package typically includes:
55
+
56
+ - `src/`: Contains the source code for the package, including:
57
+ - `Factory/`: Contains factory classes for creating email providers.
58
+ - `Provider/`: Contains classes that implement the email sending logic.
59
+ - `Transformer/`: Contains classes for transforming email messages to the required format.
60
+ - `Type/`: Contains type definitions and interfaces.
61
+ - `tests/`: Contains unit tests for the package.
62
+ - `README.md`: Documentation for the package.
63
+ - `.env`: Environment variables for configuration.
64
+
65
+ ## Installation
66
+
67
+ Install the package using pnpm:
68
+
69
+ ```bash
70
+ pnpm add @messagekit/core
71
+ ```
72
+
73
+ ## Features
74
+
75
+ - **Unified Messaging Interfaces**: Define consistent interfaces for handling message-related actions, such as downloading attachments, sending messages, and handling webhooks.
76
+ - **AI Integration Ready**: Tools are designed to wrap actions and services, allowing them to be easily integrated into AI workflows, especially with structured validation using Zod.
77
+ - **Extensible and Reusable**: Easily extend the provided base classes and interfaces to fit your specific messaging needs.
78
+
79
+ ## Usage
80
+
81
+ ### Sending an Email
82
+
83
+ The `sendEmail` function is the primary method for sending emails. It can be used as follows:
84
+
85
+ ```typescript
86
+ import { sendEmail } from '@messagekit/core';
87
+
88
+ const emailMessage = {
89
+ from: [{ email: 'sender@example.com', name: 'Sender Name' }],
90
+ to: [{ email: 'recipient@example.com', name: 'Recipient Name' }],
91
+ subject: 'Hello from MessageKit',
92
+ text: 'This is a test email sent using MessageKit.',
93
+ html: '<p>This is a test email sent using MessageKit.</p>',
94
+ attachments: [
95
+ {
96
+ content: 'base64-encoded-content',
97
+ filename: 'attachment.txt',
98
+ path: '/path/to/attachment.txt',
99
+ },
100
+ ],
101
+ };
102
+
103
+ const config = {
104
+ PROVIDER_NAME: process.env.PROVIDER_NAME, // any supported service from @messagekit/[PROVIDER_NAME]
105
+ RESEND_API_KEY: process.env.RESEND_API_KEY,
106
+ RESEND_API_URL: process.env.RESEND_API_URL,
107
+ };
108
+
109
+ sendEmail(emailMessage, config)
110
+ .then(response => {
111
+ console.log('Email sent successfully:', response);
112
+ })
113
+ .catch(error => {
114
+ console.error('Error sending email:', error);
115
+ });
116
+ ```
117
+
118
+ ### Configuration
119
+
120
+ Configuration for the `sendEmail` function can be defined in a `.env` file. The naming convention for the configuration variables is as follows:
121
+
122
+ - `PROVIDER_NAME`: The email service provider (e.g., 'sendgrid', 'mailgun', 'resend').
123
+ - `RESEND_API_KEY`: The API key for authenticating with the Resend API, for Nylas it will be `NYLAS_API_KEY`, and so on...
124
+ - `RESEND_API_URL`: An optional custom API URL.
125
+
126
+ Example `.env` file:
127
+
128
+ ```
129
+ RESEND_API_KEY=your_resend_api_key
130
+ RESEND_API_URL=https://api.resend.com
131
+ ```
132
+
133
+ ### Extensibility
134
+
135
+ The `@messagekit/core` package is designed to be extensible. You can create new email providers by implementing the `EmailProviderFactoryInterface` and `EmailSenderInterface`. This allows you to add support for additional email services in the future.
136
+
137
+ ## Rationale
138
+
139
+ The `@messagekit/core` package is designed to provide a consistent and extensible foundation for managing messaging workflows in TypeScript applications. By using well-defined interfaces and tools, developers can easily integrate messaging capabilities into their domain-driven designs and AI-driven processes. The library also leverages Zod for schema validation, ensuring that the data being processed meets the expected structure.
140
+
141
+ ## Serverless Focus
142
+
143
+ This package focuses on serverless (nodeless) environments, which is why it implements integrations with raw HTTP APIs.
144
+
145
+ ## Installation & Setup
146
+
147
+ Install the package using pnpm:
148
+
149
+ ```bash
150
+ pnpm add @messagekit/core
151
+ pnpm add @messagekit/resend
152
+ ```
153
+
154
+ Ensure that your project is set up to handle TypeScript and supports ES modules, as this library is built with modern JavaScript standards.
155
+
156
+ ## Contributing
157
+
158
+ Contributions are welcome! Feel free to fork this project and submit pull requests. Before submitting, please ensure your code passes all linting and unit tests.
159
+
160
+ You can format code using:
161
+
162
+ ```bash
163
+ pnpm format
164
+ ```
165
+
166
+ You can run unit tests using:
167
+
168
+ ```bash
169
+ pnpm test
@@ -0,0 +1,16 @@
1
+ import type { CaptchaInterface } from '../Interface/index.js';
2
+ import type { CaptchaFactoryInterface } from '../Interface/index.js';
3
+ import type { TypeBaseConfig } from '../Type/index.js';
4
+ /**
5
+ * Interface representing an captcha provider factory.
6
+ */
7
+ export declare class CaptchaFactory implements CaptchaFactoryInterface<TypeBaseConfig> {
8
+ /**
9
+ * Creates an captcha based on the provided configuration.
10
+ *
11
+ * @param {TypeConfig} config - The configuration object for the email provider.
12
+ * @returns {Promise<CaptchaInterface>} - An captcha instance.
13
+ * @throws {Error} - Throws an error when requested provider captcha can't be created.
14
+ */
15
+ create(config: TypeBaseConfig): Promise<CaptchaInterface>;
16
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Interface representing an captcha provider factory.
3
+ */
4
+ export class CaptchaFactory {
5
+ /**
6
+ * Creates an captcha based on the provided configuration.
7
+ *
8
+ * @param {TypeConfig} config - The configuration object for the email provider.
9
+ * @returns {Promise<CaptchaInterface>} - An captcha instance.
10
+ * @throws {Error} - Throws an error when requested provider captcha can't be created.
11
+ */
12
+ async create(config) {
13
+ try {
14
+ const providerName = config.CAPTCHA_PROVIDER ?? 'core';
15
+ const packageName = '@captcha/' + providerName;
16
+ // Dynamically import the package and access the default export
17
+ // eslint-disable-next-line @typescript-eslint/naming-convention
18
+ const ProviderModule = await import(packageName);
19
+ // eslint-disable-next-line @typescript-eslint/naming-convention
20
+ const Factory = ProviderModule.default;
21
+ // we need to check if Factory has the create method, required by the EmailProviderFactoryInterface
22
+ if (typeof Factory !== 'function' || !('create' in Factory.prototype)) {
23
+ throw new Error('The provider module does not implement the required interface.');
24
+ }
25
+ // Instantiate the factory and create the captcha
26
+ return new Factory().create(config);
27
+ }
28
+ catch (error) {
29
+ throw new Error(`Failed to create a captcha for the provider "${config.CAPTCHA_PROVIDER}".`);
30
+ }
31
+ }
32
+ }
@@ -0,0 +1 @@
1
+ export * from './CaptchaFactory.js';
@@ -0,0 +1 @@
1
+ export * from './CaptchaFactory.js';
@@ -0,0 +1,8 @@
1
+ import type { TypeBaseConfig } from '../Type/index.js';
2
+ /**
3
+ * Gets the captcha form element for the provided configuration.
4
+ *
5
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
6
+ * @returns {Promise<React.FC>} - The captcha form element.
7
+ */
8
+ export declare const getCaptchaFormElement: (config: TypeBaseConfig) => Promise<React.FC>;
@@ -0,0 +1,8 @@
1
+ import { CaptchaFactory } from '../Factory/index.js';
2
+ /**
3
+ * Gets the captcha form element for the provided configuration.
4
+ *
5
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
6
+ * @returns {Promise<React.FC>} - The captcha form element.
7
+ */
8
+ export const getCaptchaFormElement = async (config) => (await (new CaptchaFactory()).create(config)).getCaptchaFormElement();
@@ -0,0 +1,8 @@
1
+ import type { TypeBaseConfig } from '../Type/index.js';
2
+ /**
3
+ * Gets the captcha script for the provided configuration.
4
+ *
5
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
6
+ * @returns {Promise<React.FC>} - The captcha script.
7
+ */
8
+ export declare const getCaptchaScript: (config: TypeBaseConfig) => Promise<React.FC>;
@@ -0,0 +1,8 @@
1
+ import { CaptchaFactory } from '../Factory/index.js';
2
+ /**
3
+ * Gets the captcha script for the provided configuration.
4
+ *
5
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
6
+ * @returns {Promise<React.FC>} - The captcha script.
7
+ */
8
+ export const getCaptchaScript = async (config) => (await (new CaptchaFactory()).create(config)).getCaptchaScript();
@@ -0,0 +1,3 @@
1
+ export * from './getCaptchaFormElement.js';
2
+ export * from './getCaptchaScript.js';
3
+ export * from './verifyCaptcha.js';
@@ -0,0 +1,3 @@
1
+ export * from './getCaptchaFormElement.js';
2
+ export * from './getCaptchaScript.js';
3
+ export * from './verifyCaptcha.js';
@@ -0,0 +1,9 @@
1
+ import type { TypeBaseConfig } from '../Type/index.js';
2
+ /**
3
+ * Verifies the captcha response.
4
+ *
5
+ * @param {Record<string, any>} formFieldValues - The form field values to verify.
6
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
7
+ * @returns {Promise<boolean>} - Returns true if the captcha is verified.
8
+ */
9
+ export declare const verifyCaptcha: (formFieldValues: Record<string, any>, config: TypeBaseConfig) => Promise<boolean>;
@@ -0,0 +1,9 @@
1
+ import { CaptchaFactory } from '../Factory/index.js';
2
+ /**
3
+ * Verifies the captcha response.
4
+ *
5
+ * @param {Record<string, any>} formFieldValues - The form field values to verify.
6
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
7
+ * @returns {Promise<boolean>} - Returns true if the captcha is verified.
8
+ */
9
+ export const verifyCaptcha = async (formFieldValues, config) => (await (new CaptchaFactory()).create(config)).verifyCaptcha(formFieldValues);
@@ -0,0 +1,15 @@
1
+ import type { TypeBaseConfig } from '../Type/Types.js';
2
+ import type { CaptchaInterface } from './CaptchaInterface.js';
3
+ /**
4
+ * Interface representing an captcha provider factory.
5
+ */
6
+ export interface CaptchaFactoryInterface<TypeConfig extends TypeBaseConfig = TypeBaseConfig> {
7
+ /**
8
+ * Creates an captcha based on the provided configuration.
9
+ *
10
+ * @param {TypeConfig} config - The configuration object for the captcha provider.
11
+ * @returns {Promise<CaptchaInterface>} - An captcha instance.
12
+ * @throws {Error} - Throws an error when requested provider captcha can't be created.
13
+ */
14
+ create(config: TypeConfig): Promise<CaptchaInterface>;
15
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ export interface CaptchaInterface {
2
+ /**
3
+ * Verify captcha
4
+ * @param {Record<string, any>} formFieldValues - Form field values
5
+ * @returns {Promise<boolean>} - Returns true if captcha is verified
6
+ */
7
+ verifyCaptcha(formFieldValues: Record<string, any>): Promise<boolean>;
8
+ /**
9
+ * Get captcha script
10
+ * @returns {React.FC} - Returns captcha script
11
+ */
12
+ getCaptchaScript(): React.FC;
13
+ /**
14
+ * Get captcha form element
15
+ * @returns {React.FC} - Returns captcha form element
16
+ */
17
+ getCaptchaFormElement(): React.FC;
18
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './CaptchaFactoryInterface.js';
2
+ export * from './CaptchaInterface.js';
@@ -0,0 +1,2 @@
1
+ export * from './CaptchaFactoryInterface.js';
2
+ export * from './CaptchaInterface.js';
@@ -0,0 +1,3 @@
1
+ export interface TypeBaseConfig {
2
+ CAPTCHA_PROVIDER: string;
3
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from './Types.js';
@@ -0,0 +1 @@
1
+ export * from './Types.js';
@@ -0,0 +1,4 @@
1
+ export * from './Factory/index.js';
2
+ export * from './Interface/index.js';
3
+ export * from './Type/index.js';
4
+ export * from './Function/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './Factory/index.js';
2
+ export * from './Interface/index.js';
3
+ export * from './Type/index.js';
4
+ export * from './Function/index.js';
@@ -0,0 +1,6 @@
1
+ import eslintConfig from '@dmitryrechkin/eslint-standard/eslint.config.mjs';
2
+
3
+ export default eslintConfig({
4
+ tsconfigPath: './tsconfig.eslint.json',
5
+ ignores: ['packages/**', 'tests/**'],
6
+ });
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@captcha-kit/core",
3
+ "type": "module",
4
+ "version": "1.0.0",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "devDependencies": {
8
+ "@dmitryrechkin/eslint-standard": "^1.0.7",
9
+ "fix-esm-import-path": "^1.0.1",
10
+ "dotenv": "^16.4.5",
11
+ "eslint": "^8.0.0",
12
+ "eslint-plugin-unused-imports": "^3.0.0",
13
+ "tsconfig-paths": "^4.2.0",
14
+ "typescript": "^5.5.3",
15
+ "vitest": "^0.24.5",
16
+ "shx": "^0.3.4",
17
+ "@types/react": "^18.0.0"
18
+ },
19
+ "dependencies": {
20
+ "react": "^18.3.1",
21
+ "react-dom": "^18.3.1"
22
+ },
23
+ "scripts": {
24
+ "lint": "eslint .",
25
+ "format": "eslint --fix .",
26
+ "test": "vitest run",
27
+ "check": "tsc --noEmit",
28
+ "build": "shx rm -rf dist && tsc && fix-esm-import-path dist",
29
+ "package:tgz": "pnpm pack",
30
+ "package:publish": "pnpm publish --access public"
31
+ }
32
+ }
@@ -0,0 +1,44 @@
1
+ import type { CaptchaInterface } from '../Interface';
2
+ import type { CaptchaFactoryInterface } from '../Interface';
3
+ import type { TypeBaseConfig } from '../Type';
4
+
5
+ /**
6
+ * Interface representing an captcha provider factory.
7
+ */
8
+ export class CaptchaFactory implements CaptchaFactoryInterface<TypeBaseConfig>
9
+ {
10
+ /**
11
+ * Creates an captcha based on the provided configuration.
12
+ *
13
+ * @param {TypeConfig} config - The configuration object for the email provider.
14
+ * @returns {Promise<CaptchaInterface>} - An captcha instance.
15
+ * @throws {Error} - Throws an error when requested provider captcha can't be created.
16
+ */
17
+ public async create(config: TypeBaseConfig): Promise<CaptchaInterface>
18
+ {
19
+ try
20
+ {
21
+ const providerName = config.CAPTCHA_PROVIDER ?? 'core';
22
+ const packageName = '@captcha/' + providerName;
23
+
24
+ // Dynamically import the package and access the default export
25
+ // eslint-disable-next-line @typescript-eslint/naming-convention
26
+ const ProviderModule = await import(packageName);
27
+ // eslint-disable-next-line @typescript-eslint/naming-convention
28
+ const Factory = ProviderModule.default;
29
+
30
+ // we need to check if Factory has the create method, required by the EmailProviderFactoryInterface
31
+ if (typeof Factory !== 'function' || !('create' in Factory.prototype))
32
+ {
33
+ throw new Error('The provider module does not implement the required interface.');
34
+ }
35
+
36
+ // Instantiate the factory and create the captcha
37
+ return new Factory().create(config as any);
38
+ }
39
+ catch (error)
40
+ {
41
+ throw new Error(`Failed to create a captcha for the provider "${config.CAPTCHA_PROVIDER}".`);
42
+ }
43
+ }
44
+ }
@@ -0,0 +1 @@
1
+ export * from './CaptchaFactory';
@@ -0,0 +1,11 @@
1
+ import type { TypeBaseConfig } from '../Type';
2
+ import { CaptchaFactory } from '../Factory';
3
+
4
+ /**
5
+ * Gets the captcha form element for the provided configuration.
6
+ *
7
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
8
+ * @returns {Promise<React.FC>} - The captcha form element.
9
+ */
10
+ export const getCaptchaFormElement = async (config: TypeBaseConfig): Promise<React.FC> =>
11
+ (await (new CaptchaFactory()).create(config)).getCaptchaFormElement();
@@ -0,0 +1,11 @@
1
+ import type { TypeBaseConfig } from '../Type';
2
+ import { CaptchaFactory } from '../Factory';
3
+
4
+ /**
5
+ * Gets the captcha script for the provided configuration.
6
+ *
7
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
8
+ * @returns {Promise<React.FC>} - The captcha script.
9
+ */
10
+ export const getCaptchaScript = async (config: TypeBaseConfig): Promise<React.FC> =>
11
+ (await (new CaptchaFactory()).create(config)).getCaptchaScript();
@@ -0,0 +1,3 @@
1
+ export * from './getCaptchaFormElement';
2
+ export * from './getCaptchaScript';
3
+ export * from './verifyCaptcha';
@@ -0,0 +1,12 @@
1
+ import type { TypeBaseConfig } from '../Type';
2
+ import { CaptchaFactory } from '../Factory';
3
+
4
+ /**
5
+ * Verifies the captcha response.
6
+ *
7
+ * @param {Record<string, any>} formFieldValues - The form field values to verify.
8
+ * @param {TypeBaseConfig} config - The configuration object for the captcha provider.
9
+ * @returns {Promise<boolean>} - Returns true if the captcha is verified.
10
+ */
11
+ export const verifyCaptcha = async (formFieldValues: Record<string, any>, config: TypeBaseConfig): Promise<boolean> =>
12
+ (await (new CaptchaFactory()).create(config)).verifyCaptcha(formFieldValues);
@@ -0,0 +1,17 @@
1
+ import type { TypeBaseConfig } from '../Type/Types';
2
+ import type { CaptchaInterface } from './CaptchaInterface';
3
+
4
+ /**
5
+ * Interface representing an captcha provider factory.
6
+ */
7
+ export interface CaptchaFactoryInterface<TypeConfig extends TypeBaseConfig = TypeBaseConfig>
8
+ {
9
+ /**
10
+ * Creates an captcha based on the provided configuration.
11
+ *
12
+ * @param {TypeConfig} config - The configuration object for the captcha provider.
13
+ * @returns {Promise<CaptchaInterface>} - An captcha instance.
14
+ * @throws {Error} - Throws an error when requested provider captcha can't be created.
15
+ */
16
+ create(config: TypeConfig): Promise<CaptchaInterface>;
17
+ }
@@ -0,0 +1,21 @@
1
+ export interface CaptchaInterface
2
+ {
3
+ /**
4
+ * Verify captcha
5
+ * @param {Record<string, any>} formFieldValues - Form field values
6
+ * @returns {Promise<boolean>} - Returns true if captcha is verified
7
+ */
8
+ verifyCaptcha(formFieldValues: Record<string, any>): Promise<boolean>;
9
+
10
+ /**
11
+ * Get captcha script
12
+ * @returns {React.FC} - Returns captcha script
13
+ */
14
+ getCaptchaScript(): React.FC;
15
+
16
+ /**
17
+ * Get captcha form element
18
+ * @returns {React.FC} - Returns captcha form element
19
+ */
20
+ getCaptchaFormElement(): React.FC;
21
+ }
@@ -0,0 +1,2 @@
1
+ export * from './CaptchaFactoryInterface';
2
+ export * from './CaptchaInterface';
@@ -0,0 +1,6 @@
1
+ // Base configuration for all configuration types, the expectation is that each provider will have its own configuration type that extends this.
2
+ export interface TypeBaseConfig
3
+ {
4
+ // eslint-disable-next-line @typescript-eslint/naming-convention
5
+ CAPTCHA_PROVIDER: string;
6
+ }
@@ -0,0 +1 @@
1
+ export * from './Types';
package/src/index.tsx ADDED
@@ -0,0 +1,4 @@
1
+ export * from './Factory';
2
+ export * from './Interface';
3
+ export * from './Type';
4
+ export * from './Function';
@@ -0,0 +1,25 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { getCaptchaFormElement } from '../src/Function/getCaptchaFormElement';
3
+ import type { TypeBaseConfig } from '../src/Type/Types';
4
+ import React from 'react';
5
+
6
+ vi.mock('../src/Factory', () => {
7
+ return {
8
+ CaptchaFactory: vi.fn().mockImplementation(() => {
9
+ return {
10
+ create: vi.fn().mockResolvedValue({
11
+ getCaptchaFormElement: () => () => <form>Mocked Form</form>
12
+ })
13
+ };
14
+ })
15
+ };
16
+ });
17
+
18
+ describe('getCaptchaFormElement', () => {
19
+ it('should return a React component for the captcha form element', async () => {
20
+ const config: TypeBaseConfig = { CAPTCHA_PROVIDER: 'test-provider' };
21
+ const formElement = await getCaptchaFormElement(config);
22
+ expect(formElement).toBeDefined();
23
+ expect(typeof formElement).toBe('function'); // Check if it's a React component
24
+ });
25
+ });
@@ -0,0 +1,25 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { getCaptchaScript } from '../src/Function/getCaptchaScript';
3
+ import type { TypeBaseConfig } from '../src/Type/Types';
4
+ import React from 'react';
5
+
6
+ vi.mock('../src/Factory', () => {
7
+ return {
8
+ CaptchaFactory: vi.fn().mockImplementation(() => {
9
+ return {
10
+ create: vi.fn().mockResolvedValue({
11
+ getCaptchaScript: () => () => <div>Mocked Script</div>
12
+ })
13
+ };
14
+ })
15
+ };
16
+ });
17
+
18
+ describe('getCaptchaScript', () => {
19
+ it('should return a React component for the captcha script', async () => {
20
+ const config: TypeBaseConfig = { CAPTCHA_PROVIDER: 'test-provider' };
21
+ const scriptComponent = await getCaptchaScript(config);
22
+ expect(scriptComponent).toBeDefined();
23
+ expect(typeof scriptComponent).toBe('function'); // Check if it's a React component
24
+ });
25
+ });