unshared-clientjs-sdk 2.3.0 → 3.0.0-rc.15

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 (72) hide show
  1. package/README.md +349 -152
  2. package/dist/client.d.ts +54 -25
  3. package/dist/client.js +1 -1
  4. package/dist/esm/client.d.mts +54 -25
  5. package/dist/esm/client.mjs +1 -1
  6. package/dist/esm/index.d.mts +8 -8
  7. package/dist/esm/index.mjs +1 -1
  8. package/dist/esm/middleware/dispatch-processing.d.mts +11 -5
  9. package/dist/esm/middleware/dispatch-processing.mjs +1 -1
  10. package/dist/esm/middleware/index.d.mts +10 -6
  11. package/dist/esm/middleware/index.mjs +1 -1
  12. package/dist/esm/middleware/injection/fingerprint-script.d.mts +9 -0
  13. package/dist/esm/middleware/injection/fingerprint-script.mjs +1 -1
  14. package/dist/esm/middleware/injection/fp-bundle-source.d.mts +5 -4
  15. package/dist/esm/middleware/injection/fp-bundle-source.mjs +1 -1
  16. package/dist/esm/middleware/response-interceptor.d.mts +1 -1
  17. package/dist/esm/middleware/routes/interstitial.d.mts +2 -2
  18. package/dist/esm/middleware/routes/interstitial.mjs +1 -1
  19. package/dist/esm/middleware/routes/submit-fp.d.mts +5 -5
  20. package/dist/esm/middleware/routes/submit-fp.mjs +1 -1
  21. package/dist/esm/middleware/routes/verify.d.mts +5 -4
  22. package/dist/esm/middleware/routes/verify.mjs +1 -1
  23. package/dist/esm/middleware/utils/client-ip.d.mts +1 -1
  24. package/dist/esm/middleware/utils/cookies.d.mts +1 -1
  25. package/dist/esm/middleware/utils/device-id.d.mts +5 -3
  26. package/dist/esm/middleware/utils/device-id.mjs +1 -1
  27. package/dist/esm/middleware/utils/flagged-response.mjs +1 -1
  28. package/dist/esm/middleware/utils/http-helpers.d.mts +1 -1
  29. package/dist/esm/middleware/utils/permanent-device-id.d.mts +7 -0
  30. package/dist/esm/middleware/utils/permanent-device-id.mjs +1 -0
  31. package/dist/esm/middleware/utils/read-json-body.d.mts +3 -0
  32. package/dist/esm/middleware/utils/read-json-body.mjs +1 -0
  33. package/dist/esm/middleware/utils/secure.d.mts +1 -1
  34. package/dist/esm/middleware.d.mts +5 -6
  35. package/dist/esm/middleware.mjs +1 -1
  36. package/dist/esm/shared-types.d.mts +148 -0
  37. package/dist/esm/web/index.d.mts +6 -6
  38. package/dist/esm/web/index.mjs +1 -1
  39. package/dist/esm/web/protection-handler.d.mts +5 -5
  40. package/dist/esm/web/protection-handler.mjs +1 -1
  41. package/dist/esm/web/submit-handler.d.mts +2 -2
  42. package/dist/esm/web/submit-handler.mjs +1 -1
  43. package/dist/esm/web/types.d.mts +5 -3
  44. package/dist/esm/web/web-helpers.d.mts +13 -1
  45. package/dist/esm/web/web-helpers.mjs +1 -1
  46. package/dist/middleware/dispatch-processing.d.ts +8 -2
  47. package/dist/middleware/dispatch-processing.js +1 -1
  48. package/dist/middleware/index.d.ts +5 -1
  49. package/dist/middleware/index.js +1 -1
  50. package/dist/middleware/injection/fingerprint-script.d.ts +9 -0
  51. package/dist/middleware/injection/fingerprint-script.js +1 -1
  52. package/dist/middleware/injection/fp-bundle-source.d.ts +5 -4
  53. package/dist/middleware/injection/fp-bundle-source.js +1 -1
  54. package/dist/middleware/routes/submit-fp.js +1 -1
  55. package/dist/middleware/routes/verify.d.ts +2 -1
  56. package/dist/middleware/routes/verify.js +1 -1
  57. package/dist/middleware/utils/device-id.d.ts +4 -2
  58. package/dist/middleware/utils/device-id.js +1 -1
  59. package/dist/middleware/utils/permanent-device-id.d.ts +7 -0
  60. package/dist/middleware/utils/permanent-device-id.js +1 -0
  61. package/dist/middleware/utils/read-json-body.d.ts +3 -0
  62. package/dist/middleware/utils/read-json-body.js +1 -0
  63. package/dist/middleware.d.ts +3 -4
  64. package/dist/middleware.js +1 -1
  65. package/dist/shared-types.d.ts +148 -0
  66. package/dist/web/protection-handler.d.ts +1 -1
  67. package/dist/web/protection-handler.js +1 -1
  68. package/dist/web/submit-handler.js +1 -1
  69. package/dist/web/types.d.ts +4 -2
  70. package/dist/web/web-helpers.d.ts +13 -1
  71. package/dist/web/web-helpers.js +1 -1
  72. package/package.json +4 -4
@@ -69,13 +69,15 @@ export interface WebProtectionConfig {
69
69
  includePathPrefix?: string[];
70
70
  /** Skip the bot/crawler UA filter. Set to true in test environments so automated browsers (Playwright, Puppeteer, etc.) can observe verdicts. @default false */
71
71
  disableBotFilter?: boolean;
72
+ /** Enable diagnostic logging in the injected fingerprint script. @default false */
73
+ debug?: boolean;
72
74
  /** Hard timeout (ms) for checkUser on cache miss. Fails open on timeout. @default 1500 */
73
75
  checkUserTimeoutMs?: number;
74
76
  /** Resolves a custom session ID. Falls back to __unshared_sid cookie. */
75
77
  sessionId?: (req: Request) => string | undefined;
76
78
  /**
77
79
  * Resolves a device ID from the request.
78
- * Falls back to X-Device-Id header → __unshared_fp_id cookie.
80
+ * Falls back to X-Device-Id header, then the canonical or legacy stable-hash cookie.
79
81
  */
80
82
  deviceId?: (req: Request) => string | undefined;
81
83
  /**
@@ -91,7 +93,7 @@ export interface WebProtectionConfig {
91
93
  * createWebProtectionMiddleware(client, { ..., fingerprintSdkBundle });
92
94
  * ```
93
95
  *
94
- * If omitted, the fp.js route returns 404. The inline script degrades
96
+ * If omitted, the fp.js route returns a noncacheable 503. The inline script degrades
95
97
  * gracefully — the cached-fingerprint path still works.
96
98
  */
97
99
  fingerprintSdkBundle?: string;
@@ -18,7 +18,8 @@ export declare function parseCookieFromRequest(request: Request, name: string):
18
18
  */
19
19
  export declare function extractClientIpFromRequest(request: Request): string;
20
20
  /**
21
- * Resolves device ID from: custom resolver → X-Device-Id header → __unshared_fp_id cookie.
21
+ * Resolves device ID from the custom resolver, X-Device-Id header, then the
22
+ * canonical __unshared_stable_hash cookie or legacy __unshared_fp_id cookie.
22
23
  * Mirrors `extractDeviceIdOrUndefined` in src/middleware/utils/device-id.ts.
23
24
  */
24
25
  export declare function extractDeviceIdFromRequest(request: Request, resolveDeviceId?: (req: Request) => string | undefined): string | undefined;
@@ -32,6 +33,17 @@ export declare function extractDeviceIdFromRequestOrUnknown(request: Request, re
32
33
  * 2. The URL protocol (for direct HTTPS requests)
33
34
  */
34
35
  export declare function isSecureWebRequest(request: Request): boolean;
36
+ export declare function readJsonRequest(request: Request, maxBytes?: number): Promise<{
37
+ success: true;
38
+ data: unknown;
39
+ } | {
40
+ success: false;
41
+ status: 400 | 413;
42
+ error: {
43
+ code: string;
44
+ message: string;
45
+ };
46
+ }>;
35
47
  /**
36
48
  * Build a JSON response. Mirrors `sendJson(res, status, data)` in
37
49
  * src/middleware/utils/http-helpers.ts, but returns a new Response instead
@@ -1 +1 @@
1
- "use strict";function parseCookieFromRequest(e,t){const o=e.headers.get("cookie");if(!o)return;const n=o.match(new RegExp(`(?:^|; )${t}=([^;]*)`));if(n)try{return decodeURIComponent(n[1])}catch{return n[1]}}function extractClientIpFromRequest(e){const t=e.headers.get("cf-connecting-ip");if(t)return t;const o=e.headers.get("x-real-ip");if(o)return o;const n=e.headers.get("x-forwarded-for");if(n){const e=n.split(",")[0]?.trim();if(e)return e}return""}function extractDeviceIdFromRequest(e,t){if(t)try{const o=t(e);if(o)return o}catch{}const o=e.headers.get("x-device-id");if(o)return o;return parseCookieFromRequest(e,"__unshared_fp_id")||void 0}function extractDeviceIdFromRequestOrUnknown(e,t){return extractDeviceIdFromRequest(e,t)??"unknown"}function isSecureWebRequest(e){if("https"===e.headers.get("x-forwarded-proto"))return!0;try{return"https:"===new URL(e.url).protocol}catch{return!1}}function jsonResponse(e,t,o){const n=new Headers(o);return n.set("Content-Type","application/json"),new Response(JSON.stringify(t),{status:e,headers:n})}function emptyResponse(e,t){return new Response(null,{status:e,headers:new Headers(t)})}function bodyResponse(e,t,o){return new Response(t,{status:e,headers:new Headers(o)})}function appendCookieToHeaders(e,t){e.append("Set-Cookie",t)}function mergeResponseHeaders(e,t,o){const n=new Headers;e.forEach((e,t)=>{"set-cookie"!==t.toLowerCase()&&n.set(t,e)});const r="function"==typeof e.getSetCookie?e.getSetCookie():[];for(const e of r)n.append("Set-Cookie",e);if(o)for(const e of o)n.append("Set-Cookie",e);if(t)for(const[e,o]of Object.entries(t))n.set(e,o);return n}Object.defineProperty(exports,"t",{value:!0}),exports.parseCookieFromRequest=parseCookieFromRequest,exports.extractClientIpFromRequest=extractClientIpFromRequest,exports.extractDeviceIdFromRequest=extractDeviceIdFromRequest,exports.extractDeviceIdFromRequestOrUnknown=extractDeviceIdFromRequestOrUnknown,exports.isSecureWebRequest=isSecureWebRequest,exports.jsonResponse=jsonResponse,exports.emptyResponse=emptyResponse,exports.bodyResponse=bodyResponse,exports.appendCookieToHeaders=appendCookieToHeaders,exports.mergeResponseHeaders=mergeResponseHeaders;
1
+ "use strict";function parseCookieFromRequest(e,t){const s=e.headers.get("cookie");if(!s)return;const o=s.match(new RegExp(`(?:^|; )${t}=([^;]*)`));if(o)try{return decodeURIComponent(o[1])}catch{return o[1]}}function extractClientIpFromRequest(e){const t=e.headers.get("cf-connecting-ip");if(t)return t;const s=e.headers.get("x-real-ip");if(s)return s;const o=e.headers.get("x-forwarded-for");if(o){const e=o.split(",")[0]?.trim();if(e)return e}return""}function extractDeviceIdFromRequest(e,t){if(t)try{const s=t(e);if(s)return s}catch{}const s=e.headers.get("x-device-id");if(s)return s;return parseCookieFromRequest(e,"__unshared_stable_hash")||parseCookieFromRequest(e,"__unshared_fp_id")||void 0}function extractDeviceIdFromRequestOrUnknown(e,t){return extractDeviceIdFromRequest(e,t)??"unknown"}function isSecureWebRequest(e){if("https"===e.headers.get("x-forwarded-proto"))return!0;try{return"https:"===new URL(e.url).protocol}catch{return!1}}async function readJsonRequest(e,t=1<<20){const s=Number(e.headers.get("content-length"));if(Number.isFinite(s)&&s>t)return{success:!1,status:413,error:{code:"REQUEST_TOO_LARGE",message:"Request body exceeds 1 MiB"}};try{if(!e.body)throw new Error("Missing body");const s=e.body.getReader(),o=[];let r=0;for(;;){const{done:e,value:n}=await s.read();if(e)break;if(r+=n.byteLength,r>t)return s.cancel().catch(()=>{}),{success:!1,status:413,error:{code:"REQUEST_TOO_LARGE",message:"Request body exceeds 1 MiB"}};o.push(n)}const n=new Uint8Array(r);let c=0;for(const e of o)n.set(e,c),c+=e.byteLength;return{success:!0,data:JSON.parse((new TextDecoder).decode(n))}}catch{return{success:!1,status:400,error:{code:"INVALID_JSON",message:"Request body is not valid JSON."}}}}function jsonResponse(e,t,s){const o=new Headers(s);return o.set("Content-Type","application/json"),new Response(JSON.stringify(t),{status:e,headers:o})}function emptyResponse(e,t){return new Response(null,{status:e,headers:new Headers(t)})}function bodyResponse(e,t,s){return new Response(t,{status:e,headers:new Headers(s)})}function appendCookieToHeaders(e,t){e.append("Set-Cookie",t)}function mergeResponseHeaders(e,t,s){const o=new Headers;e.forEach((e,t)=>{"set-cookie"!==t.toLowerCase()&&o.set(t,e)});const r="function"==typeof e.getSetCookie?e.getSetCookie():[];for(const e of r)o.append("Set-Cookie",e);if(s)for(const e of s)o.append("Set-Cookie",e);if(t)for(const[e,s]of Object.entries(t))o.set(e,s);return o}Object.defineProperty(exports,"t",{value:!0}),exports.parseCookieFromRequest=parseCookieFromRequest,exports.extractClientIpFromRequest=extractClientIpFromRequest,exports.extractDeviceIdFromRequest=extractDeviceIdFromRequest,exports.extractDeviceIdFromRequestOrUnknown=extractDeviceIdFromRequestOrUnknown,exports.isSecureWebRequest=isSecureWebRequest,exports.readJsonRequest=readJsonRequest,exports.jsonResponse=jsonResponse,exports.emptyResponse=emptyResponse,exports.bodyResponse=bodyResponse,exports.appendCookieToHeaders=appendCookieToHeaders,exports.mergeResponseHeaders=mergeResponseHeaders;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "unshared-clientjs-sdk",
3
- "version": "2.3.0",
4
- "description": "Server-side Node.js SDK for the Unshared Labs V2 API",
3
+ "version": "3.0.0-rc.15",
4
+ "description": "Server-side Node.js SDK for the Unshared Labs API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/esm/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -52,12 +52,12 @@
52
52
  "author": "",
53
53
  "license": "MIT",
54
54
  "dependencies": {
55
- "unshared-frontend-sdk": "2.3.0"
55
+ "unshared-frontend-sdk": "3.0.0-rc.15"
56
56
  },
57
57
  "devDependencies": {
58
- "@unshared-labs/shared-types": "file:../../../shared/types",
59
58
  "@types/express": "^4.17.21",
60
59
  "@types/node": "^24.10.1",
60
+ "@unshared-labs/shared-types": "file:../../../shared/types",
61
61
  "express": "^4.18.2",
62
62
  "terser": "^5.44.1",
63
63
  "ts-node": "^10.9.2",