From b894c68270471376bfb95f879b8a899ae97f531a Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 11:06:17 -0300 Subject: [PATCH 01/14] feat(source): export loader source --- lib/esbuild.config.js | 10 +++++++++- package.json | 19 ++++++++++++++++--- source.d.ts | 2 ++ source.js | 3 +++ test/source-export.test.mjs | 38 +++++++++++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 source.d.ts create mode 100644 source.js create mode 100644 test/source-export.test.mjs diff --git a/lib/esbuild.config.js b/lib/esbuild.config.js index 03e70cc..1d88cc0 100644 --- a/lib/esbuild.config.js +++ b/lib/esbuild.config.js @@ -1,4 +1,4 @@ -import { readFileSync } from 'fs'; +import { readFileSync, writeFileSync } from 'fs'; import path, { resolve } from 'path'; import { fileURLToPath } from 'url'; @@ -114,6 +114,14 @@ if (WATCH) { ] }); + const loaderSource = readFileSync(resolve(DIST, 'index.es5.js'), 'utf-8') + .replace(/<\/script/gi, '<\\/script'); + + writeFileSync( + resolve(DIST, 'source.cjs'), + `'use strict';\n\n// Generated from index.es5.js. Do not edit.\nmodule.exports = ${JSON.stringify(loaderSource)};\n` + ); + // Add Polyfills await build({ ...config, diff --git a/package.json b/package.json index 3966bbd..0bfb906 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,24 @@ "main": "./dist/index.mjs", "types": "./dist/types/src/index.d.ts", "exports": { - "import": "./dist/index.mjs", - "require": "./dist/index.cjs" + ".": { + "types": "./dist/types/src/index.d.ts", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + }, + "./source": { + "types": "./source.d.ts", + "react-native": "./source.js", + "import": "./source.js", + "require": "./dist/source.cjs", + "default": "./source.js" + } }, "files": [ "README.md", "dist", + "source.d.ts", + "source.js", "!**/*.tsbuildinfo" ], "repository": { @@ -33,7 +45,8 @@ "fix:lint": "pnpm -r --stream run fix:lint", "test:lint": "pnpm -r --stream run test:lint", "test:types": "pnpm -r --stream run test:types", - "test:unit": "pnpm -r --stream run test:unit", + "test:unit": "pnpm -r --stream run test:unit && pnpm run test:source", + "test:source": "pnpm run build:lib && node --test ./test/source-export.test.mjs", "test:integration": "playwright test -c playwright.config.ts" }, "devDependencies": { diff --git a/source.d.ts b/source.d.ts new file mode 100644 index 0000000..6294fdf --- /dev/null +++ b/source.d.ts @@ -0,0 +1,2 @@ +declare const hCaptchaLoaderSource: string; +export default hCaptchaLoaderSource; diff --git a/source.js b/source.js new file mode 100644 index 0000000..da47dcf --- /dev/null +++ b/source.js @@ -0,0 +1,3 @@ +import hCaptchaLoaderSource from './dist/source.cjs'; + +export default hCaptchaLoaderSource; diff --git a/test/source-export.test.mjs b/test/source-export.test.mjs new file mode 100644 index 0000000..88450f7 --- /dev/null +++ b/test/source-export.test.mjs @@ -0,0 +1,38 @@ +import assert from 'node:assert/strict'; +import { createRequire } from 'node:module'; +import test from 'node:test'; +import vm from 'node:vm'; + +import { hCaptchaLoader } from '@hcaptcha/loader'; +import hCaptchaLoaderSource from '@hcaptcha/loader/source'; + +const require = createRequire(import.meta.url); +const requiredLoader = require('@hcaptcha/loader'); +const requiredSource = require('@hcaptcha/loader/source'); + +test('preserves the existing ESM and CommonJS loader exports', () => { + assert.equal(typeof hCaptchaLoader, 'function'); + assert.equal(typeof requiredLoader.hCaptchaLoader, 'function'); +}); + +test('exports the same source to ESM and CommonJS consumers', () => { + assert.equal(typeof hCaptchaLoaderSource, 'string'); + assert.equal(requiredSource, hCaptchaLoaderSource); +}); + +test('exports source that is safe to embed in a script element', () => { + assert.doesNotMatch(hCaptchaLoaderSource, /<\/script/i); +}); + +test('registers hCaptchaLoader on window', () => { + const context = { + clearTimeout, + console, + setTimeout, + window: {}, + }; + + vm.runInNewContext(hCaptchaLoaderSource, context); + + assert.equal(typeof context.window.hCaptchaLoader, 'function'); +}); From b2e798f2f790afa9e54e671644467d00a7627191 Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 12:06:03 -0300 Subject: [PATCH 02/14] chore: simplify source export conditions --- package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index 0bfb906..ee95d6b 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,8 @@ }, "./source": { "types": "./source.d.ts", - "react-native": "./source.js", "import": "./source.js", - "require": "./dist/source.cjs", - "default": "./source.js" + "require": "./dist/source.cjs" } }, "files": [ From 5af8add1a9b944abefb2dac1f923031f4a9305a9 Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 12:25:26 -0300 Subject: [PATCH 03/14] chore: align source export layout --- .github/workflows/pull_request.yaml | 4 ++- {test => __test__}/source-export.test.mjs | 34 +++++++++++++++++++++++ lib/esbuild.config.js | 10 +++++++ package.json | 12 ++++---- source.d.ts | 2 -- source.js | 3 -- 6 files changed, 52 insertions(+), 13 deletions(-) rename {test => __test__}/source-export.test.mjs (51%) delete mode 100644 source.d.ts delete mode 100644 source.js diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index f05de82..125eb2e 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -59,4 +59,6 @@ jobs: - name: Setup environment and dependencies uses: ./.github/actions/setup - name: Run Unit Tests - run: pnpm run test:unit \ No newline at end of file + run: pnpm run test:unit + - name: Run Package Export Tests + run: pnpm run test:exports diff --git a/test/source-export.test.mjs b/__test__/source-export.test.mjs similarity index 51% rename from test/source-export.test.mjs rename to __test__/source-export.test.mjs index 88450f7..2732828 100644 --- a/test/source-export.test.mjs +++ b/__test__/source-export.test.mjs @@ -1,12 +1,18 @@ import assert from 'node:assert/strict'; +import { execFileSync } from 'node:child_process'; +import { mkdtempSync, rmSync } from 'node:fs'; import { createRequire } from 'node:module'; +import { tmpdir } from 'node:os'; +import { dirname, join } from 'node:path'; import test from 'node:test'; +import { fileURLToPath } from 'node:url'; import vm from 'node:vm'; import { hCaptchaLoader } from '@hcaptcha/loader'; import hCaptchaLoaderSource from '@hcaptcha/loader/source'; const require = createRequire(import.meta.url); +const root = dirname(dirname(fileURLToPath(import.meta.url))); const requiredLoader = require('@hcaptcha/loader'); const requiredSource = require('@hcaptcha/loader/source'); @@ -36,3 +42,31 @@ test('registers hCaptchaLoader on window', () => { assert.equal(typeof context.window.hCaptchaLoader, 'function'); }); + +test('includes every source export artifact in the package', () => { + const npmCache = mkdtempSync(join(tmpdir(), 'hcaptcha-loader-npm-')); + + try { + const output = execFileSync( + 'npm', + ['pack', '--dry-run', '--ignore-scripts', '--json'], + { + cwd: root, + encoding: 'utf8', + env: { + ...process.env, + npm_config_cache: npmCache, + npm_config_loglevel: 'silent', + }, + } + ); + const [{ files }] = JSON.parse(output); + const packagedFiles = new Set(files.map(({ path }) => path)); + + assert.equal(packagedFiles.has('dist/source.cjs'), true); + assert.equal(packagedFiles.has('dist/source.mjs'), true); + assert.equal(packagedFiles.has('dist/source.d.ts'), true); + } finally { + rmSync(npmCache, { force: true, recursive: true }); + } +}); diff --git a/lib/esbuild.config.js b/lib/esbuild.config.js index 1d88cc0..5fca0c3 100644 --- a/lib/esbuild.config.js +++ b/lib/esbuild.config.js @@ -122,6 +122,16 @@ if (WATCH) { `'use strict';\n\n// Generated from index.es5.js. Do not edit.\nmodule.exports = ${JSON.stringify(loaderSource)};\n` ); + writeFileSync( + resolve(DIST, 'source.mjs'), + '// Generated from index.es5.js. Do not edit.\nimport hCaptchaLoaderSource from \'./source.cjs\';\n\nexport default hCaptchaLoaderSource;\n' + ); + + writeFileSync( + resolve(DIST, 'source.d.ts'), + 'declare const hCaptchaLoaderSource: string;\nexport default hCaptchaLoaderSource;\n' + ); + // Add Polyfills await build({ ...config, diff --git a/package.json b/package.json index ee95d6b..8c5f67f 100644 --- a/package.json +++ b/package.json @@ -18,16 +18,14 @@ "require": "./dist/index.cjs" }, "./source": { - "types": "./source.d.ts", - "import": "./source.js", + "types": "./dist/source.d.ts", + "import": "./dist/source.mjs", "require": "./dist/source.cjs" } }, "files": [ "README.md", "dist", - "source.d.ts", - "source.js", "!**/*.tsbuildinfo" ], "repository": { @@ -41,10 +39,10 @@ "display:demo": "http-server ./ --cors -d -o ./demo/src", "serve:demo": "http-server ./", "fix:lint": "pnpm -r --stream run fix:lint", - "test:lint": "pnpm -r --stream run test:lint", + "test:lint": "eslint -c .eslintrc.json lib/esbuild.config.js __test__/source-export.test.mjs && pnpm -r --stream run test:lint", "test:types": "pnpm -r --stream run test:types", - "test:unit": "pnpm -r --stream run test:unit && pnpm run test:source", - "test:source": "pnpm run build:lib && node --test ./test/source-export.test.mjs", + "test:unit": "pnpm -r --stream run test:unit", + "test:exports": "pnpm run build:lib && node --test ./__test__/source-export.test.mjs", "test:integration": "playwright test -c playwright.config.ts" }, "devDependencies": { diff --git a/source.d.ts b/source.d.ts deleted file mode 100644 index 6294fdf..0000000 --- a/source.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -declare const hCaptchaLoaderSource: string; -export default hCaptchaLoaderSource; diff --git a/source.js b/source.js deleted file mode 100644 index da47dcf..0000000 --- a/source.js +++ /dev/null @@ -1,3 +0,0 @@ -import hCaptchaLoaderSource from './dist/source.cjs'; - -export default hCaptchaLoaderSource; From 12e73cf4b041746146cb87493c76acf55aec3fd0 Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 12:29:04 -0300 Subject: [PATCH 04/14] test: remove source export coverage --- .github/workflows/pull_request.yaml | 2 - __test__/source-export.test.mjs | 72 ----------------------------- package.json | 3 +- 3 files changed, 1 insertion(+), 76 deletions(-) delete mode 100644 __test__/source-export.test.mjs diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index 125eb2e..a91c530 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -60,5 +60,3 @@ jobs: uses: ./.github/actions/setup - name: Run Unit Tests run: pnpm run test:unit - - name: Run Package Export Tests - run: pnpm run test:exports diff --git a/__test__/source-export.test.mjs b/__test__/source-export.test.mjs deleted file mode 100644 index 2732828..0000000 --- a/__test__/source-export.test.mjs +++ /dev/null @@ -1,72 +0,0 @@ -import assert from 'node:assert/strict'; -import { execFileSync } from 'node:child_process'; -import { mkdtempSync, rmSync } from 'node:fs'; -import { createRequire } from 'node:module'; -import { tmpdir } from 'node:os'; -import { dirname, join } from 'node:path'; -import test from 'node:test'; -import { fileURLToPath } from 'node:url'; -import vm from 'node:vm'; - -import { hCaptchaLoader } from '@hcaptcha/loader'; -import hCaptchaLoaderSource from '@hcaptcha/loader/source'; - -const require = createRequire(import.meta.url); -const root = dirname(dirname(fileURLToPath(import.meta.url))); -const requiredLoader = require('@hcaptcha/loader'); -const requiredSource = require('@hcaptcha/loader/source'); - -test('preserves the existing ESM and CommonJS loader exports', () => { - assert.equal(typeof hCaptchaLoader, 'function'); - assert.equal(typeof requiredLoader.hCaptchaLoader, 'function'); -}); - -test('exports the same source to ESM and CommonJS consumers', () => { - assert.equal(typeof hCaptchaLoaderSource, 'string'); - assert.equal(requiredSource, hCaptchaLoaderSource); -}); - -test('exports source that is safe to embed in a script element', () => { - assert.doesNotMatch(hCaptchaLoaderSource, /<\/script/i); -}); - -test('registers hCaptchaLoader on window', () => { - const context = { - clearTimeout, - console, - setTimeout, - window: {}, - }; - - vm.runInNewContext(hCaptchaLoaderSource, context); - - assert.equal(typeof context.window.hCaptchaLoader, 'function'); -}); - -test('includes every source export artifact in the package', () => { - const npmCache = mkdtempSync(join(tmpdir(), 'hcaptcha-loader-npm-')); - - try { - const output = execFileSync( - 'npm', - ['pack', '--dry-run', '--ignore-scripts', '--json'], - { - cwd: root, - encoding: 'utf8', - env: { - ...process.env, - npm_config_cache: npmCache, - npm_config_loglevel: 'silent', - }, - } - ); - const [{ files }] = JSON.parse(output); - const packagedFiles = new Set(files.map(({ path }) => path)); - - assert.equal(packagedFiles.has('dist/source.cjs'), true); - assert.equal(packagedFiles.has('dist/source.mjs'), true); - assert.equal(packagedFiles.has('dist/source.d.ts'), true); - } finally { - rmSync(npmCache, { force: true, recursive: true }); - } -}); diff --git a/package.json b/package.json index 8c5f67f..67e60bd 100644 --- a/package.json +++ b/package.json @@ -39,10 +39,9 @@ "display:demo": "http-server ./ --cors -d -o ./demo/src", "serve:demo": "http-server ./", "fix:lint": "pnpm -r --stream run fix:lint", - "test:lint": "eslint -c .eslintrc.json lib/esbuild.config.js __test__/source-export.test.mjs && pnpm -r --stream run test:lint", + "test:lint": "pnpm -r --stream run test:lint", "test:types": "pnpm -r --stream run test:types", "test:unit": "pnpm -r --stream run test:unit", - "test:exports": "pnpm run build:lib && node --test ./__test__/source-export.test.mjs", "test:integration": "playwright test -c playwright.config.ts" }, "devDependencies": { From 01d7c2e62319eb897a682ac747bbf6b8c0937db6 Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 12:30:48 -0300 Subject: [PATCH 05/14] chore: restore pull request workflow --- .github/workflows/pull_request.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yaml b/.github/workflows/pull_request.yaml index a91c530..f05de82 100644 --- a/.github/workflows/pull_request.yaml +++ b/.github/workflows/pull_request.yaml @@ -59,4 +59,4 @@ jobs: - name: Setup environment and dependencies uses: ./.github/actions/setup - name: Run Unit Tests - run: pnpm run test:unit + run: pnpm run test:unit \ No newline at end of file From f8a56406dd6d934a38a435dfd85f50f77efca684 Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 16:47:24 -0300 Subject: [PATCH 06/14] feat: export inline loader script --- lib/esbuild.config.js | 37 ++++++++++++++++++++----------------- lib/src/inline.ts | 3 +++ package.json | 8 ++++---- 3 files changed, 27 insertions(+), 21 deletions(-) create mode 100644 lib/src/inline.ts diff --git a/lib/esbuild.config.js b/lib/esbuild.config.js index 5fca0c3..7e3ac2a 100644 --- a/lib/esbuild.config.js +++ b/lib/esbuild.config.js @@ -1,4 +1,4 @@ -import { readFileSync, writeFileSync } from 'fs'; +import { readFileSync } from 'fs'; import path, { resolve } from 'path'; import { fileURLToPath } from 'url'; @@ -114,23 +114,26 @@ if (WATCH) { ] }); - const loaderSource = readFileSync(resolve(DIST, 'index.es5.js'), 'utf-8') - .replace(/<\/script/gi, '<\\/script'); - - writeFileSync( - resolve(DIST, 'source.cjs'), - `'use strict';\n\n// Generated from index.es5.js. Do not edit.\nmodule.exports = ${JSON.stringify(loaderSource)};\n` - ); - - writeFileSync( - resolve(DIST, 'source.mjs'), - '// Generated from index.es5.js. Do not edit.\nimport hCaptchaLoaderSource from \'./source.cjs\';\n\nexport default hCaptchaLoaderSource;\n' - ); + // Package the browser script as a string without executing it. + await build({ + entryPoints: [resolve(DIST, 'index.es5.js')], + loader: { + '.js': 'text', + }, + format: 'cjs', + minify: true, + outfile: resolve(DIST, 'inline.cjs'), + }); - writeFileSync( - resolve(DIST, 'source.d.ts'), - 'declare const hCaptchaLoaderSource: string;\nexport default hCaptchaLoaderSource;\n' - ); + await build({ + entryPoints: [resolve(DIST, 'index.es5.js')], + loader: { + '.js': 'text', + }, + format: 'esm', + minify: true, + outfile: resolve(DIST, 'inline.mjs'), + }); // Add Polyfills await build({ diff --git a/lib/src/inline.ts b/lib/src/inline.ts new file mode 100644 index 0000000..3d8b6db --- /dev/null +++ b/lib/src/inline.ts @@ -0,0 +1,3 @@ +declare const hCaptchaLoaderInlineScript: string; + +export default hCaptchaLoaderInlineScript; diff --git a/package.json b/package.json index 67e60bd..39a00ec 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,10 @@ "import": "./dist/index.mjs", "require": "./dist/index.cjs" }, - "./source": { - "types": "./dist/source.d.ts", - "import": "./dist/source.mjs", - "require": "./dist/source.cjs" + "./inline": { + "types": "./dist/types/src/inline.d.ts", + "import": "./dist/inline.mjs", + "require": "./dist/inline.cjs" } }, "files": [ From abb80475867e3a40ebfa7fe869b49dfc4d2794ae Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 16:53:34 -0300 Subject: [PATCH 07/14] chore: refactor --- lib/esbuild.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/esbuild.config.js b/lib/esbuild.config.js index 7e3ac2a..fc9a828 100644 --- a/lib/esbuild.config.js +++ b/lib/esbuild.config.js @@ -114,7 +114,7 @@ if (WATCH) { ] }); - // Package the browser script as a string without executing it. + // Package the browser script await build({ entryPoints: [resolve(DIST, 'index.es5.js')], loader: { From b88a26735f9b26f52c4892089ff179400b01ca4d Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 16:57:48 -0300 Subject: [PATCH 08/14] chore: refactor --- lib/esbuild.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/esbuild.config.js b/lib/esbuild.config.js index fc9a828..03ee17a 100644 --- a/lib/esbuild.config.js +++ b/lib/esbuild.config.js @@ -114,7 +114,7 @@ if (WATCH) { ] }); - // Package the browser script + // Bundle the loader as inline script await build({ entryPoints: [resolve(DIST, 'index.es5.js')], loader: { From a5b5c697a245743d840c2c5a767ae7ef86821beb Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Mon, 13 Jul 2026 17:10:26 -0300 Subject: [PATCH 09/14] chore: bump version to 2.4.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 39a00ec..3b231e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@hcaptcha/loader", "description": "This is a JavaScript library to easily configure the loading of the hCaptcha JS client SDK with built-in error handling.", - "version": "2.3.0", + "version": "2.4.0", "author": "hCaptcha team and contributors", "license": "MIT", "keywords": [ From da64106ca69067ca428003bf0bc83fabff96d47f Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Tue, 14 Jul 2026 11:58:08 -0300 Subject: [PATCH 10/14] feat: add modern browser bundles --- lib/esbuild.config.js | 44 ++++++++++++++++++++++--------------------- lib/src/browser.ts | 11 +++++++++++ package.json | 7 +++++-- 3 files changed, 39 insertions(+), 23 deletions(-) create mode 100644 lib/src/browser.ts diff --git a/lib/esbuild.config.js b/lib/esbuild.config.js index 03ee17a..0f0dd13 100644 --- a/lib/esbuild.config.js +++ b/lib/esbuild.config.js @@ -91,6 +91,29 @@ if (WATCH) { treeShaking: true, }); + // Build the loader for modern browser + await build({ + ...config, + entryPoints: [resolve(SRC, 'browser.ts')], + format: 'iife', + outfile: resolve(DIST, 'index.browser.js'), + treeShaking: true, + target: [ + 'es6', + ] + }); + + // Build the modern browser bundle as importable string + await build({ + entryPoints: [resolve(DIST, 'index.browser.js')], + loader: { + '.js': 'text', + }, + format: 'esm', + minify: true, + outfile: resolve(DIST, 'index.inline.js'), + }); + // Transform to ES5 const transformedESM = await swc.transformFile(resolve(DIST, 'index.mjs'), swcOptions); @@ -114,27 +137,6 @@ if (WATCH) { ] }); - // Bundle the loader as inline script - await build({ - entryPoints: [resolve(DIST, 'index.es5.js')], - loader: { - '.js': 'text', - }, - format: 'cjs', - minify: true, - outfile: resolve(DIST, 'inline.cjs'), - }); - - await build({ - entryPoints: [resolve(DIST, 'index.es5.js')], - loader: { - '.js': 'text', - }, - format: 'esm', - minify: true, - outfile: resolve(DIST, 'inline.mjs'), - }); - // Add Polyfills await build({ ...config, diff --git a/lib/src/browser.ts b/lib/src/browser.ts new file mode 100644 index 0000000..3e33365 --- /dev/null +++ b/lib/src/browser.ts @@ -0,0 +1,11 @@ +import { hCaptchaLoader } from './loader'; + +import type { ILoaderParams } from './types.js'; + +declare global { + interface Window { + hCaptchaLoader: (params?: ILoaderParams) => Promise; + } +} + +window.hCaptchaLoader = hCaptchaLoader; diff --git a/package.json b/package.json index 3b231e8..7bb5940 100644 --- a/package.json +++ b/package.json @@ -17,10 +17,13 @@ "import": "./dist/index.mjs", "require": "./dist/index.cjs" }, + "./browser": { + "types": "./dist/types/src/browser.d.ts", + "import": "./dist/index.browser.js" + }, "./inline": { "types": "./dist/types/src/inline.d.ts", - "import": "./dist/inline.mjs", - "require": "./dist/inline.cjs" + "import": "./dist/index.inline.js" } }, "files": [ From 5878b34efb232ea9e0da8b8c1834415cf00d613b Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Tue, 14 Jul 2026 13:45:49 -0300 Subject: [PATCH 11/14] feat: support orientation query parameter --- lib/__test__/loader.test.ts | 19 +++++++++++++++++++ lib/src/loader.ts | 1 + lib/src/types.ts | 1 + 3 files changed, 21 insertions(+) diff --git a/lib/__test__/loader.test.ts b/lib/__test__/loader.test.ts index c1d1ed1..2763439 100644 --- a/lib/__test__/loader.test.ts +++ b/lib/__test__/loader.test.ts @@ -59,6 +59,25 @@ describe('hCaptchaLoader', () => { }); }); + it('should include orientation in the script query', async () => { + cleanupScripts(); + mockFetchScript.mockResolvedValueOnce(SCRIPT_COMPLETE); + + const promise = hCaptchaLoader({ orientation: 'landscape', sentry: false }); + + await waitFor(() => { + expect(mockFetchScript).toHaveBeenCalledWith( + expect.objectContaining({ + query: expect.stringContaining('orientation=landscape'), + }), + expect.any(Function) + ); + + window[HCAPTCHA_LOAD_FN_NAME](); + expect(promise).resolves.toEqual((window as any).hcaptcha); + }); + }); + it('should not fetch script since it was already loaded', async () => { const result = await hCaptchaLoader({ sentry: false }); expect(result).toEqual((window as any).hcaptcha); diff --git a/lib/src/loader.ts b/lib/src/loader.ts index a5fc7fe..d8480a9 100644 --- a/lib/src/loader.ts +++ b/lib/src/loader.ts @@ -60,6 +60,7 @@ export function hCaptchaApi(params: ILoaderParams = { cleanup: false }, sentry: host: params.host, recaptchacompat: params.recaptchacompat, hl: params.hl, + orientation: params.orientation, uj: params.uj, }); diff --git a/lib/src/types.ts b/lib/src/types.ts index 19a1195..e6c9d00 100644 --- a/lib/src/types.ts +++ b/lib/src/types.ts @@ -21,6 +21,7 @@ export interface ILoaderParams extends IScriptParams { host?: string; recaptchacompat?: string; hl?: string; + orientation?: string; cleanup?: boolean; uj?: boolean; maxRetries?: number; From e96798848192e64012e156161a9251c4e3e97b94 Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Tue, 14 Jul 2026 15:42:37 -0300 Subject: [PATCH 12/14] refactor: keep orientation out of loader config --- lib/__test__/loader.test.ts | 19 ------------------- lib/src/loader.ts | 1 - lib/src/types.ts | 1 - 3 files changed, 21 deletions(-) diff --git a/lib/__test__/loader.test.ts b/lib/__test__/loader.test.ts index 2763439..c1d1ed1 100644 --- a/lib/__test__/loader.test.ts +++ b/lib/__test__/loader.test.ts @@ -59,25 +59,6 @@ describe('hCaptchaLoader', () => { }); }); - it('should include orientation in the script query', async () => { - cleanupScripts(); - mockFetchScript.mockResolvedValueOnce(SCRIPT_COMPLETE); - - const promise = hCaptchaLoader({ orientation: 'landscape', sentry: false }); - - await waitFor(() => { - expect(mockFetchScript).toHaveBeenCalledWith( - expect.objectContaining({ - query: expect.stringContaining('orientation=landscape'), - }), - expect.any(Function) - ); - - window[HCAPTCHA_LOAD_FN_NAME](); - expect(promise).resolves.toEqual((window as any).hcaptcha); - }); - }); - it('should not fetch script since it was already loaded', async () => { const result = await hCaptchaLoader({ sentry: false }); expect(result).toEqual((window as any).hcaptcha); diff --git a/lib/src/loader.ts b/lib/src/loader.ts index d8480a9..a5fc7fe 100644 --- a/lib/src/loader.ts +++ b/lib/src/loader.ts @@ -60,7 +60,6 @@ export function hCaptchaApi(params: ILoaderParams = { cleanup: false }, sentry: host: params.host, recaptchacompat: params.recaptchacompat, hl: params.hl, - orientation: params.orientation, uj: params.uj, }); diff --git a/lib/src/types.ts b/lib/src/types.ts index e6c9d00..19a1195 100644 --- a/lib/src/types.ts +++ b/lib/src/types.ts @@ -21,7 +21,6 @@ export interface ILoaderParams extends IScriptParams { host?: string; recaptchacompat?: string; hl?: string; - orientation?: string; cleanup?: boolean; uj?: boolean; maxRetries?: number; From bf65d5494a2b43f89f24816722a99ec64bf49acf Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Tue, 14 Jul 2026 18:27:09 -0300 Subject: [PATCH 13/14] chore: address feedback --- lib/esbuild.config.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/esbuild.config.js b/lib/esbuild.config.js index 0f0dd13..78cbebf 100644 --- a/lib/esbuild.config.js +++ b/lib/esbuild.config.js @@ -96,7 +96,7 @@ if (WATCH) { ...config, entryPoints: [resolve(SRC, 'browser.ts')], format: 'iife', - outfile: resolve(DIST, 'index.browser.js'), + outfile: resolve(DIST, 'browser.js'), treeShaking: true, target: [ 'es6', @@ -105,7 +105,7 @@ if (WATCH) { // Build the modern browser bundle as importable string await build({ - entryPoints: [resolve(DIST, 'index.browser.js')], + entryPoints: [resolve(DIST, 'browser.js')], loader: { '.js': 'text', }, diff --git a/package.json b/package.json index 7bb5940..f7b9e35 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ }, "./browser": { "types": "./dist/types/src/browser.d.ts", - "import": "./dist/index.browser.js" + "import": "./dist/browser.js" }, "./inline": { "types": "./dist/types/src/inline.d.ts", From 85f62bfcb601135f249b60d51091ea8c3ff51469 Mon Sep 17 00:00:00 2001 From: Damian Nunez Rodriguez Date: Tue, 14 Jul 2026 18:29:24 -0300 Subject: [PATCH 14/14] chore: address feedback --- lib/esbuild.config.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/esbuild.config.js b/lib/esbuild.config.js index 78cbebf..9376733 100644 --- a/lib/esbuild.config.js +++ b/lib/esbuild.config.js @@ -111,7 +111,7 @@ if (WATCH) { }, format: 'esm', minify: true, - outfile: resolve(DIST, 'index.inline.js'), + outfile: resolve(DIST, 'inline.js'), }); // Transform to ES5 diff --git a/package.json b/package.json index f7b9e35..e477617 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ }, "./inline": { "types": "./dist/types/src/inline.d.ts", - "import": "./dist/index.inline.js" + "import": "./dist/inline.js" } }, "files": [