@internetarchive/recaptcha-manager 0.1.2-alpha.1 → 1.0.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/.editorconfig +29 -29
- package/.github/workflows/ci.yml +27 -26
- package/.github/workflows/gh-pages-main.yml +39 -0
- package/.github/workflows/pr-preview.yml +63 -0
- package/.husky/pre-commit +1 -4
- package/.prettierignore +1 -0
- package/LICENSE +661 -661
- package/README.md +63 -85
- package/coverage/.gitignore +3 -0
- package/coverage/.placeholder +0 -0
- package/demo/app-root.ts +93 -93
- package/demo/index.html +21 -21
- package/dist/demo/app-root.d.ts +14 -14
- package/dist/demo/app-root.js +85 -85
- package/dist/demo/app-root.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/src/recaptcha-manager.d.ts +34 -35
- package/dist/src/recaptcha-manager.js +54 -52
- package/dist/src/recaptcha-manager.js.map +1 -1
- package/dist/src/recaptcha-widget.d.ts +38 -39
- package/dist/src/recaptcha-widget.js +95 -95
- package/dist/src/recaptcha-widget.js.map +1 -1
- package/dist/test/mock-grecaptcha.d.ts +23 -24
- package/dist/test/mock-grecaptcha.js +59 -61
- package/dist/test/mock-grecaptcha.js.map +1 -1
- package/dist/test/mock-lazy-loader.d.ts +15 -15
- package/dist/test/mock-lazy-loader.js +17 -16
- package/dist/test/mock-lazy-loader.js.map +1 -1
- package/dist/test/recaptcha-manager.test.d.ts +1 -1
- package/dist/test/recaptcha-manager.test.js +137 -137
- package/dist/test/recaptcha-manager.test.js.map +1 -1
- package/dist/vite.config.d.ts +2 -0
- package/dist/vite.config.js +25 -0
- package/dist/vite.config.js.map +1 -0
- package/eslint.config.mjs +53 -0
- package/index.ts +10 -10
- package/package.json +76 -98
- package/renovate.json +6 -0
- package/src/recaptcha-manager.ts +89 -87
- package/src/recaptcha-widget.ts +148 -148
- package/ssl/server.crt +22 -0
- package/ssl/server.key +28 -0
- package/test/mock-grecaptcha.ts +85 -87
- package/test/mock-lazy-loader.ts +39 -38
- package/test/recaptcha-manager.test.ts +151 -151
- package/tsconfig.json +31 -20
- package/vite.config.ts +25 -0
- package/web-dev-server.config.mjs +32 -28
- package/web-test-runner.config.mjs +41 -41
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import typescriptEslint from '@typescript-eslint/eslint-plugin';
|
|
2
|
+
import html from 'eslint-plugin-html';
|
|
3
|
+
import tsParser from '@typescript-eslint/parser';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import js from '@eslint/js';
|
|
7
|
+
import { FlatCompat } from '@eslint/eslintrc';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
const compat = new FlatCompat({
|
|
12
|
+
baseDirectory: __dirname,
|
|
13
|
+
recommendedConfig: js.configs.recommended,
|
|
14
|
+
allConfig: js.configs.all,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export default [
|
|
18
|
+
...compat.extends('plugin:@typescript-eslint/recommended'),
|
|
19
|
+
{
|
|
20
|
+
plugins: {
|
|
21
|
+
'@typescript-eslint': typescriptEslint,
|
|
22
|
+
html,
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
languageOptions: {
|
|
26
|
+
parser: tsParser,
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
settings: {
|
|
30
|
+
'import/resolver': {
|
|
31
|
+
node: {
|
|
32
|
+
extensions: ['.ts', '.tsx'],
|
|
33
|
+
moduleDirectory: ['node_modules', 'src', 'demo'],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
rules: {
|
|
39
|
+
'@typescript-eslint/no-unsafe-function-type': 'warn',
|
|
40
|
+
'@typescript-eslint/no-unused-vars': 'warn',
|
|
41
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
ignores: ['**/*.js', '**/*.mjs'],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
files: ['**/*.test.ts'],
|
|
49
|
+
rules: {
|
|
50
|
+
'@typescript-eslint/no-unused-expressions': 'off',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
];
|
package/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export {
|
|
2
|
-
RecaptchaManager,
|
|
3
|
-
RecaptchaManagerInterface,
|
|
4
|
-
} from './src/recaptcha-manager
|
|
5
|
-
|
|
6
|
-
export {
|
|
7
|
-
RecaptchaWidget,
|
|
8
|
-
RecaptchaWidgetInterface,
|
|
9
|
-
RecaptchaWidgetConfig,
|
|
10
|
-
} from './src/recaptcha-widget
|
|
1
|
+
export {
|
|
2
|
+
RecaptchaManager,
|
|
3
|
+
RecaptchaManagerInterface,
|
|
4
|
+
} from './src/recaptcha-manager';
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
RecaptchaWidget,
|
|
8
|
+
RecaptchaWidgetInterface,
|
|
9
|
+
RecaptchaWidgetConfig,
|
|
10
|
+
} from './src/recaptcha-widget';
|
package/package.json
CHANGED
|
@@ -1,98 +1,76 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@internetarchive/recaptcha-manager",
|
|
3
|
-
"description": "A library that lets you lazy load and interact with reCaptcha.",
|
|
4
|
-
"repository": {
|
|
5
|
-
"type": "git",
|
|
6
|
-
"url": "git+https://github.com/internetarchive/iaux-recaptcha-manager.git"
|
|
7
|
-
},
|
|
8
|
-
"license": "AGPL-3.0-only",
|
|
9
|
-
"author": "Internet Archive",
|
|
10
|
-
"version": "
|
|
11
|
-
"main": "dist/index.js",
|
|
12
|
-
"module": "dist/index.js",
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"build": "tsc",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"test": "tsc &&
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"@open-wc/
|
|
31
|
-
"@
|
|
32
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
33
|
-
"@typescript-eslint/parser": "^
|
|
34
|
-
"@web/dev-server": "^0.
|
|
35
|
-
"@web/test-runner": "^0.
|
|
36
|
-
"concurrently": "^
|
|
37
|
-
"eslint": "^
|
|
38
|
-
"eslint-config-prettier": "^
|
|
39
|
-
"eslint-plugin-
|
|
40
|
-
"eslint-plugin-
|
|
41
|
-
"eslint-plugin-
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"import/extensions": [
|
|
78
|
-
"off",
|
|
79
|
-
"ignorePackages",
|
|
80
|
-
{
|
|
81
|
-
"js": "never",
|
|
82
|
-
"ts": "never"
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
}
|
|
86
|
-
},
|
|
87
|
-
"prettier": {
|
|
88
|
-
"singleQuote": true,
|
|
89
|
-
"arrowParens": "avoid"
|
|
90
|
-
},
|
|
91
|
-
"lint-staged": {
|
|
92
|
-
"*.ts": [
|
|
93
|
-
"eslint --fix",
|
|
94
|
-
"prettier --write",
|
|
95
|
-
"git add"
|
|
96
|
-
]
|
|
97
|
-
}
|
|
98
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@internetarchive/recaptcha-manager",
|
|
3
|
+
"description": "A library that lets you lazy load and interact with reCaptcha.",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/internetarchive/iaux-recaptcha-manager.git"
|
|
7
|
+
},
|
|
8
|
+
"license": "AGPL-3.0-only",
|
|
9
|
+
"author": "Internet Archive",
|
|
10
|
+
"version": "1.0.0",
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"module": "dist/index.js",
|
|
13
|
+
"scripts": {
|
|
14
|
+
"start": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
|
|
15
|
+
"prepare": "rimraf dist && tsc && husky install",
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"lint": "eslint . && prettier \"**/*.ts\" --check",
|
|
18
|
+
"format": "eslint . --fix && prettier \"**/*.ts\" --write",
|
|
19
|
+
"circular": "madge --circular --extensions ts .",
|
|
20
|
+
"test": "tsc && npm run lint && npm run circular && wtr --coverage",
|
|
21
|
+
"test:watch": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wtr --watch\"",
|
|
22
|
+
"ghpages:build": "rimraf ghpages && npm run prepare && vite build",
|
|
23
|
+
"ghpages:publish": "npm run ghpages:prepare -e $(git branch --show-current)",
|
|
24
|
+
"ghpages:prepare": "npm run ghpages:build && touch ghpages/.nojekyll && npm run ghpages:generate",
|
|
25
|
+
"ghpages:generate": "gh-pages -t -d ghpages -m \"Build for $(git log --pretty=format:\"%h %an %ai %s\" -n1) [skip ci]\""
|
|
26
|
+
},
|
|
27
|
+
"types": "dist/index.d.ts",
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@open-wc/eslint-config": "^12.0.3",
|
|
30
|
+
"@open-wc/testing": "^4.0.0",
|
|
31
|
+
"@types/mocha": "^10.0.10",
|
|
32
|
+
"@typescript-eslint/eslint-plugin": "^8.19.1",
|
|
33
|
+
"@typescript-eslint/parser": "^8.19.1",
|
|
34
|
+
"@web/dev-server": "^0.4.6",
|
|
35
|
+
"@web/test-runner": "^0.20.0",
|
|
36
|
+
"concurrently": "^9.1.2",
|
|
37
|
+
"eslint": "^9.17.0",
|
|
38
|
+
"eslint-config-prettier": "^10.1.1",
|
|
39
|
+
"eslint-plugin-html": "^8.1.2",
|
|
40
|
+
"eslint-plugin-import": "^2.31.0",
|
|
41
|
+
"eslint-plugin-lit": "^1.15.0",
|
|
42
|
+
"eslint-plugin-lit-a11y": "^4.1.4",
|
|
43
|
+
"eslint-plugin-no-only-tests": "^3.3.0",
|
|
44
|
+
"eslint-plugin-wc": "^2.2.0",
|
|
45
|
+
"gh-pages": "^6.3.0",
|
|
46
|
+
"husky": "^9.1.7",
|
|
47
|
+
"madge": "^8.0.0",
|
|
48
|
+
"nanoevents": "^6.0.2",
|
|
49
|
+
"prettier": "^3.4.2",
|
|
50
|
+
"rimraf": "^6.0.1",
|
|
51
|
+
"sinon": "^19.0.2",
|
|
52
|
+
"ts-lit-plugin": "^2.0.2",
|
|
53
|
+
"tslib": "^2.8.1",
|
|
54
|
+
"typescript": "^5.7.2",
|
|
55
|
+
"vite": "^6.0.7"
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
},
|
|
60
|
+
"prettier": {
|
|
61
|
+
"singleQuote": true,
|
|
62
|
+
"arrowParens": "avoid"
|
|
63
|
+
},
|
|
64
|
+
"lint-staged": {
|
|
65
|
+
"*.ts": [
|
|
66
|
+
"eslint --fix",
|
|
67
|
+
"prettier --write",
|
|
68
|
+
"git add"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"lit": "^2.8.0",
|
|
73
|
+
"@internetarchive/lazy-loader-service": "^0.2.0",
|
|
74
|
+
"@types/grecaptcha": "^2"
|
|
75
|
+
}
|
|
76
|
+
}
|
package/renovate.json
ADDED
package/src/recaptcha-manager.ts
CHANGED
|
@@ -1,87 +1,89 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LazyLoaderService,
|
|
3
|
-
LazyLoaderServiceInterface,
|
|
4
|
-
} from '@internetarchive/lazy-loader-service';
|
|
5
|
-
import { RecaptchaWidget, RecaptchaWidgetInterface } from './recaptcha-widget
|
|
6
|
-
|
|
7
|
-
export interface RecaptchaManagerInterface {
|
|
8
|
-
/**
|
|
9
|
-
* Load a recaptcha widget for a given site key or the default site key.
|
|
10
|
-
*/
|
|
11
|
-
getRecaptchaWidget(options?: {
|
|
12
|
-
siteKey?: string;
|
|
13
|
-
recaptchaParams?: ReCaptchaV2.Parameters;
|
|
14
|
-
}): Promise<RecaptchaWidgetInterface>;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class RecaptchaManager implements RecaptchaManagerInterface {
|
|
18
|
-
private lazyLoader: LazyLoaderServiceInterface;
|
|
19
|
-
|
|
20
|
-
private defaultSiteKey?: string;
|
|
21
|
-
|
|
22
|
-
private recaptchaCache: Record<string, RecaptchaWidget> = {};
|
|
23
|
-
|
|
24
|
-
constructor(options?: {
|
|
25
|
-
defaultSiteKey?: string;
|
|
26
|
-
lazyLoader?: LazyLoaderServiceInterface;
|
|
27
|
-
grecaptchaLibrary?: ReCaptchaV2.ReCaptcha; // allows dependency injection or will be lazy loaded
|
|
28
|
-
}) {
|
|
29
|
-
this.defaultSiteKey = options?.defaultSiteKey;
|
|
30
|
-
this.lazyLoader = options?.lazyLoader ?? new LazyLoaderService();
|
|
31
|
-
this.grecaptchaLibraryCache = options?.grecaptchaLibrary;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/** @inheritdoc */
|
|
35
|
-
async getRecaptchaWidget(options?: {
|
|
36
|
-
siteKey?: string;
|
|
37
|
-
recaptchaParams?: ReCaptchaV2.Parameters;
|
|
38
|
-
}): Promise<RecaptchaWidgetInterface> {
|
|
39
|
-
const key = options?.siteKey ?? this.defaultSiteKey;
|
|
40
|
-
if (!key) {
|
|
41
|
-
throw new Error('The reCaptcha widget requires a site key');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const cached = this.recaptchaCache[key];
|
|
45
|
-
if (cached) return cached;
|
|
46
|
-
|
|
47
|
-
const grecaptchaLibrary = await this.getRecaptchaLibrary();
|
|
48
|
-
const recaptcha = new RecaptchaWidget(
|
|
49
|
-
{
|
|
50
|
-
siteKey: key,
|
|
51
|
-
grecaptchaLibrary,
|
|
52
|
-
},
|
|
53
|
-
options?.recaptchaParams
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
this.recaptchaCache[key] = recaptcha;
|
|
57
|
-
return recaptcha;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Load the Recaptch library from Google.
|
|
62
|
-
*
|
|
63
|
-
* @returns Promise<ReCaptchaV2.ReCaptcha>
|
|
64
|
-
*/
|
|
65
|
-
private async getRecaptchaLibrary(): Promise<ReCaptchaV2.ReCaptcha> {
|
|
66
|
-
if (this.grecaptchaLibraryCache) {
|
|
67
|
-
return this.grecaptchaLibraryCache;
|
|
68
|
-
}
|
|
69
|
-
return new Promise(resolve => {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
1
|
+
import {
|
|
2
|
+
LazyLoaderService,
|
|
3
|
+
LazyLoaderServiceInterface,
|
|
4
|
+
} from '@internetarchive/lazy-loader-service';
|
|
5
|
+
import { RecaptchaWidget, RecaptchaWidgetInterface } from './recaptcha-widget';
|
|
6
|
+
|
|
7
|
+
export interface RecaptchaManagerInterface {
|
|
8
|
+
/**
|
|
9
|
+
* Load a recaptcha widget for a given site key or the default site key.
|
|
10
|
+
*/
|
|
11
|
+
getRecaptchaWidget(options?: {
|
|
12
|
+
siteKey?: string;
|
|
13
|
+
recaptchaParams?: ReCaptchaV2.Parameters;
|
|
14
|
+
}): Promise<RecaptchaWidgetInterface>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class RecaptchaManager implements RecaptchaManagerInterface {
|
|
18
|
+
private lazyLoader: LazyLoaderServiceInterface;
|
|
19
|
+
|
|
20
|
+
private defaultSiteKey?: string;
|
|
21
|
+
|
|
22
|
+
private recaptchaCache: Record<string, RecaptchaWidget> = {};
|
|
23
|
+
|
|
24
|
+
constructor(options?: {
|
|
25
|
+
defaultSiteKey?: string;
|
|
26
|
+
lazyLoader?: LazyLoaderServiceInterface;
|
|
27
|
+
grecaptchaLibrary?: ReCaptchaV2.ReCaptcha; // allows dependency injection or will be lazy loaded
|
|
28
|
+
}) {
|
|
29
|
+
this.defaultSiteKey = options?.defaultSiteKey;
|
|
30
|
+
this.lazyLoader = options?.lazyLoader ?? new LazyLoaderService();
|
|
31
|
+
this.grecaptchaLibraryCache = options?.grecaptchaLibrary;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @inheritdoc */
|
|
35
|
+
async getRecaptchaWidget(options?: {
|
|
36
|
+
siteKey?: string;
|
|
37
|
+
recaptchaParams?: ReCaptchaV2.Parameters;
|
|
38
|
+
}): Promise<RecaptchaWidgetInterface> {
|
|
39
|
+
const key = options?.siteKey ?? this.defaultSiteKey;
|
|
40
|
+
if (!key) {
|
|
41
|
+
throw new Error('The reCaptcha widget requires a site key');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const cached = this.recaptchaCache[key];
|
|
45
|
+
if (cached) return cached;
|
|
46
|
+
|
|
47
|
+
const grecaptchaLibrary = await this.getRecaptchaLibrary();
|
|
48
|
+
const recaptcha = new RecaptchaWidget(
|
|
49
|
+
{
|
|
50
|
+
siteKey: key,
|
|
51
|
+
grecaptchaLibrary,
|
|
52
|
+
},
|
|
53
|
+
options?.recaptchaParams,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
this.recaptchaCache[key] = recaptcha;
|
|
57
|
+
return recaptcha;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Load the Recaptch library from Google.
|
|
62
|
+
*
|
|
63
|
+
* @returns Promise<ReCaptchaV2.ReCaptcha>
|
|
64
|
+
*/
|
|
65
|
+
private async getRecaptchaLibrary(): Promise<ReCaptchaV2.ReCaptcha> {
|
|
66
|
+
if (this.grecaptchaLibraryCache) {
|
|
67
|
+
return this.grecaptchaLibraryCache;
|
|
68
|
+
}
|
|
69
|
+
return new Promise(resolve => {
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
+
(window as any).grecaptchaLoadedCallback = (): void => {
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
// remove the callback when we're done with it
|
|
74
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
|
+
delete (window as any).grecaptchaLoadedCallback;
|
|
76
|
+
}, 10);
|
|
77
|
+
this.grecaptchaLibraryCache = window.grecaptcha;
|
|
78
|
+
resolve(window.grecaptcha);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
this.lazyLoader.loadScript({
|
|
82
|
+
src: 'https://www.google.com/recaptcha/api.js?onload=grecaptchaLoadedCallback&render=explicit',
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** don't use directly, use `getRecaptchaLibrary()` */
|
|
88
|
+
private grecaptchaLibraryCache?: ReCaptchaV2.ReCaptcha;
|
|
89
|
+
}
|