user-agents 2.0.0-alpha.687 → 2.0.0-alpha.689

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/README.md CHANGED
@@ -194,6 +194,30 @@ const userAgent = new UserAgent([
194
194
  This example also shows that you can specify both multiple and nested properties on object filters.
195
195
 
196
196
 
197
+ ### Filtering for Modern Browsers
198
+
199
+ If you want to restrict the generated user agents to only modern browsers, you can combine User-Agents with the [browserslist](https://www.npmjs.com/package/browserslist) and [browserslist-useragent](https://www.npmjs.com/package/browserslist-useragent) packages.
200
+ The `browserslist` package lets you define what "modern" means using flexible queries like `"last 2 versions and not dead"`, and `browserslist-useragent` handles matching user agent strings against those queries.
201
+
202
+ ```javascript
203
+ import browserslist from 'browserslist';
204
+ import { matchesUA } from 'browserslist-useragent';
205
+ import UserAgent from 'user-agents';
206
+
207
+ const browsers = browserslist('last 2 versions and not dead');
208
+
209
+ function isModernBrowser(data) {
210
+ return matchesUA(data.userAgent, { browsers, allowHigherVersions: true });
211
+ }
212
+
213
+ const userAgent = new UserAgent(isModernBrowser);
214
+ ```
215
+
216
+ The `allowHigherVersions` option ensures that browser versions newer than those in the browserslist database are still accepted.
217
+ Keep in mind that the User-Agents data is already updated daily from real-world traffic, so the generated user agents are naturally skewed toward modern browsers even without explicit filtering.
218
+ You can find the full list of supported browserslist queries in the [browserslist documentation](https://github.com/browserslist/browserslist#full-list).
219
+
220
+
197
221
  ## API
198
222
 
199
223
  ### class: UserAgent([filters])
@@ -272,14 +296,30 @@ Note that each property of `data` is also accessible directly on `userAgent`.
272
296
  For example, `userAgent.appName` is equivalent to `userAgent.data.appName`.
273
297
 
274
298
 
299
+ ## Data
300
+
301
+ The dataset is built from a snapshot of the last 24 hours of real-world browser traffic, and a new version of the package is published daily with a fully refreshed dataset.
302
+ This means that the data is not accumulated over time; older browser versions are naturally phased out as they disappear from the traffic, and each release reflects a current view of the browser landscape.
303
+
304
+ User agents are not selected with uniform probability.
305
+ Each profile in the dataset is weighted according to its real-world usage frequency, so commonly seen browsers like Chrome on Windows will appear far more often than niche configurations.
306
+ The result is a random distribution that closely mirrors actual web traffic.
307
+
308
+
275
309
  ## Versioning
276
310
 
277
311
  The project follows [the Semantic Versioning guidelines](https://semver.org/).
278
312
  The automated deployments will always correspond to patch versions, and minor versions should not introduce breaking changes.
279
- It's likely that the structure of user agent data will change in the future, and this will correspond to a new major version.
280
313
 
281
- Please keep in mind that older major versions will cease to be updated after a new major version is released.
282
- You can continue to use older versions of the software, but you'll need to upgrade to get access to the latest data.
314
+ The current `latest` release on npm is v1, which is built with JavaScript and Webpack and outputs a UMD bundle.
315
+ The upcoming v2 release is available under the `next` tag (`npm install user-agents@next`) and includes several improvements:
316
+
317
+ - Rewritten in TypeScript with exported type definitions for `UserAgentData` and `Filter`.
318
+ - Built with tsup, producing native ESM and CJS entry points instead of a UMD bundle.
319
+ - Removed the `Function` class inheritance, which resolves Content Security Policy errors in browser extensions and other restricted environments.
320
+
321
+ The v1 line is deprecated and will stop receiving daily data updates once v2 is promoted to `latest`.
322
+ Both versions receive the same daily data and share an identical API surface, so upgrading should be straightforward.
283
323
 
284
324
 
285
325
  ## Acknowledgements
package/dist/index.cjs CHANGED
@@ -1,3 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }var _lodashclonedeep = require('lodash.clonedeep'); var _lodashclonedeep2 = _interopRequireDefault(_lodashclonedeep);var _useragentsjson = require('./user-agents.json'); var _useragentsjson2 = _interopRequireDefault(_useragentsjson);var o=_useragentsjson2.default,d=t=>{let a=t.reduce((e,[n])=>e+n,0),r=0;return t.map(([e,n])=>(r+=e/a,[r,n]))},f=o.map(({weight:t},a)=>[t,a]),p=d(f),u=(t,a=r=>r)=>{let r;return typeof t=="function"?r=[t]:t instanceof RegExp?r=[e=>typeof e=="object"&&e&&"userAgent"in e&&e.userAgent?t.test(e.userAgent):t.test(e)]:t instanceof Array?r=t.map(e=>u(e)):typeof t=="object"?r=Object.entries(t).map(([e,n])=>u(n,s=>s[e])):r=[e=>typeof e=="object"&&e&&"userAgent"in e&&e.userAgent?t===e.userAgent:t===e],e=>{try{let n=a(e);return r.every(s=>s(n))}catch (e2){return!1}}},A=t=>{if(!t)return p;let a=u(t),r=[];return o.forEach((e,n)=>{a(e)&&r.push([e.weight,n])}),d(r)},c=(t,a)=>{Object.defineProperty(t,"cumulativeWeightIndexPairs",{configurable:!0,enumerable:!1,writable:!1,value:a})},b,i=class t extends Function{constructor(r){super();this[b]=()=>this.data.userAgent;this.toString=()=>this.data.userAgent;this.random=()=>{let r=new t;return c(r,this.cumulativeWeightIndexPairs),r.randomize(),r};this.randomize=()=>{let r=Math.random(),[,e]=_nullishCoalesce(this.cumulativeWeightIndexPairs.find(([s])=>s>r), () => ([]));if(e==null)throw new Error("Error finding a random user agent.");let n=o[e];this.data=_lodashclonedeep2.default.call(void 0, n)};if(c(this,A(r)),this.cumulativeWeightIndexPairs.length===0)throw new Error("No user agents matched your filters.");return this.randomize(),new Proxy(this,{apply:()=>this.random(),get:(e,n,s)=>{if(e.data&&typeof n=="string"&&Object.prototype.hasOwnProperty.call(e.data,n)&&Object.prototype.propertyIsEnumerable.call(e.data,n)){let l=e.data[n];if(l!==void 0)return l}return Reflect.get(e,n,s)}})}static{b=Symbol.toPrimitive}static{this.random=r=>{try{return new t(r)}catch (e3){return null}}}};var P=i;exports.default = P;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }var _useragentsjson = require('./user-agents.json'); var _useragentsjson2 = _interopRequireDefault(_useragentsjson);var o=_useragentsjson2.default,p=r=>{let n=r.reduce((e,[s])=>e+s,0),a=0;return r.map(([e,s])=>(a+=e/n,[a,s]))},y=o.map(({weight:r},n)=>[r,n]),b=p(y),l=(r,n=a=>a)=>{let a;return typeof r=="function"?a=[r]:r instanceof RegExp?a=[e=>typeof e=="object"&&e&&"userAgent"in e&&e.userAgent?r.test(e.userAgent):r.test(e)]:r instanceof Array?a=r.map(e=>l(e)):typeof r=="object"?a=Object.entries(r).map(([e,s])=>l(s,t=>t[e])):a=[e=>typeof e=="object"&&e&&"userAgent"in e&&e.userAgent?r===e.userAgent:r===e],e=>{try{let s=n(e);return a.every(t=>t(s))}catch (e2){return!1}}},A=r=>{if(!r)return b;let n=l(r),a=[];return o.forEach((e,s)=>{n(e)&&a.push([e.weight,s])}),p(a)},g=(r,n)=>{Object.defineProperty(r,"cumulativeWeightIndexPairs",{configurable:!0,enumerable:!1,writable:!1,value:n})},d=new WeakSet,m,h,u=class r{constructor(n){this[m]=()=>this.data.userAgent;this.toString=()=>this.data.userAgent;this.random=()=>{let n=new r;return g(n,this.cumulativeWeightIndexPairs),n.randomize(),n};this.top=n=>{let a=this.cumulativeWeightIndexPairs,e=a.map(([t,i],c)=>({weight:c>0?t-a[c-1][0]:t,index:i}));e.sort((t,i)=>i.weight-t.weight);let s=n!=null?Math.min(n,e.length):e.length;return e.slice(0,s).map(({index:t})=>structuredClone(o[t]))};this.randomize=()=>{let n=Math.random(),[,a]=_nullishCoalesce(this.cumulativeWeightIndexPairs.find(([e])=>e>n), () => ([]));if(a==null)throw new Error("Error finding a random user agent.");this.data=structuredClone(o[a])};if(g(this,A(n)),this.cumulativeWeightIndexPairs.length===0)throw new Error("No user agents matched your filters.");this.randomize();let a=()=>{},e=new Proxy(a,{apply:()=>this.random(),get:(s,t)=>{if(this.data&&typeof t=="string"&&Object.prototype.hasOwnProperty.call(this.data,t)&&Object.prototype.propertyIsEnumerable.call(this.data,t)){let i=this.data[t];if(i!==void 0)return i}return Reflect.get(this,t)},set:(s,t,i)=>Reflect.set(this,t,i),defineProperty:(s,t,i)=>Reflect.defineProperty(this,t,i),getOwnPropertyDescriptor:(s,t)=>Reflect.getOwnPropertyDescriptor(this,t),has:(s,t)=>Reflect.has(this,t),deleteProperty:(s,t)=>Reflect.deleteProperty(this,t),ownKeys:()=>Reflect.ownKeys(this),getPrototypeOf:()=>r.prototype});return d.add(e),e}static[(h=Symbol.hasInstance,m=Symbol.toPrimitive,h)](n){return n instanceof Object&&d.has(n)}static{this.random=n=>{try{return new r(n)}catch (e3){return null}}}};var U=u;exports.default = U;
2
2
 
3
- module.exports = exports.default//# sourceMappingURL=index.cjs.map
3
+ module.exports = exports.default;
4
+ //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/user-agent.ts","../src/index.ts"],"names":["cloneDeep","untypedUserAgents","userAgents","makeCumulativeWeightIndexPairs","weightIndexPairs","totalWeight","sum","weight","index","defaultWeightIndexPairs","defaultCumulativeWeightIndexPairs","constructFilter","filters","accessor","parentObject","childFilters","value","childFilter","key","valueFilter","constructCumulativeWeightIndexPairsFromFilters","filter","rawUserAgent","setCumulativeWeightIndexPairs","userAgent","cumulativeWeightIndexPairs","_a","UserAgent","_UserAgent","randomNumber","cumulativeWeight","target","property","receiver","src_default"],"mappings":"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","sourcesContent":["import cloneDeep from 'lodash.clonedeep';\n\nimport untypedUserAgents from './user-agents.json' assert { type: 'json' };\n\nconst userAgents: UserAgentData[] = untypedUserAgents as UserAgentData[];\n\ntype NestedValueOf<T> = T extends object ? T[keyof T] | NestedValueOf<T[keyof T]> : T;\n\nexport type Filter<T extends UserAgentData | NestedValueOf<UserAgentData> = UserAgentData> =\n | ((parentObject: T) => boolean)\n | RegExp\n | Array<Filter<T>>\n | { [key: string]: Filter<T> }\n | string;\n\nexport interface UserAgentData {\n appName: 'Netscape';\n connection: {\n downlink: number;\n effectiveType: '3g' | '4g';\n rtt: number;\n downlinkMax?: number | null;\n type?: 'cellular' | 'wifi';\n };\n language?: string | null;\n oscpu?: string | null;\n platform:\n | 'iPad'\n | 'iPhone'\n | 'Linux aarch64'\n | 'Linux armv81'\n | 'Linux armv8l'\n | 'Linux x86_64'\n | 'MacIntel'\n | 'Win32';\n pluginsLength: number;\n screenHeight: number;\n screenWidth: number;\n userAgent: string;\n vendor: 'Apple Computer, Inc.' | 'Google Inc.' | '';\n weight: number;\n}\n\ndeclare module './user-agent' {\n export interface UserAgent extends Readonly<UserAgentData> {\n readonly cumulativeWeightIndexPairs: Array<[number, number]>;\n readonly data: UserAgentData;\n (): UserAgent;\n }\n}\n\n// Normalizes the total weight to 1 and constructs a cumulative distribution.\nconst makeCumulativeWeightIndexPairs = (\n weightIndexPairs: Array<[number, number]>,\n): Array<[number, number]> => {\n const totalWeight = weightIndexPairs.reduce((sum, [weight]) => sum + weight, 0);\n let sum = 0;\n return weightIndexPairs.map(([weight, index]) => {\n sum += weight / totalWeight;\n return [sum, index];\n });\n};\n\n// Precompute these so that we can quickly generate unfiltered user agents.\nconst defaultWeightIndexPairs: Array<[number, number]> = userAgents.map(({ weight }, index) => [\n weight,\n index,\n]);\nconst defaultCumulativeWeightIndexPairs = makeCumulativeWeightIndexPairs(defaultWeightIndexPairs);\n\n// Turn the various filter formats into a single filter function that acts on raw user agents.\nconst constructFilter = <T extends UserAgentData | NestedValueOf<UserAgentData>>(\n filters: Filter<T>,\n accessor: (parentObject: T) => T | NestedValueOf<T> = (parentObject: T): T => parentObject,\n): ((profile: T) => boolean) => {\n // WARNING: This type and a lot of the types in here are wrong, but I can't get TypeScript to\n // resolve things correctly so this will have to do for now.\n let childFilters: Array<(parentObject: T) => boolean>;\n if (typeof filters === 'function') {\n childFilters = [filters];\n } else if (filters instanceof RegExp) {\n childFilters = [\n (value: T | NestedValueOf<T>) =>\n typeof value === 'object' && value && 'userAgent' in value && value.userAgent\n ? filters.test(value.userAgent)\n : filters.test(value as string),\n ];\n } else if (filters instanceof Array) {\n childFilters = filters.map((childFilter) => constructFilter(childFilter));\n } else if (typeof filters === 'object') {\n childFilters = Object.entries(filters).map(([key, valueFilter]) =>\n constructFilter(\n valueFilter as Filter<T>,\n (parentObject: T): T | NestedValueOf<T> =>\n (parentObject as unknown as { [key: string]: NestedValueOf<T> })[key] as NestedValueOf<T>,\n ),\n );\n } else {\n childFilters = [\n (value: T | NestedValueOf<T>) =>\n typeof value === 'object' && value && 'userAgent' in value && value.userAgent\n ? filters === value.userAgent\n : filters === value,\n ];\n }\n\n return (parentObject: T) => {\n try {\n const value = accessor(parentObject);\n return childFilters.every((childFilter) => childFilter(value as T));\n } catch (error) {\n // This happens when a user-agent lacks a nested property.\n return false;\n }\n };\n};\n\n// Construct normalized cumulative weight index pairs given the filters.\nconst constructCumulativeWeightIndexPairsFromFilters = (\n filters?: Filter<UserAgentData>,\n): Array<[number, number]> => {\n if (!filters) {\n return defaultCumulativeWeightIndexPairs;\n }\n\n const filter = constructFilter(filters);\n\n const weightIndexPairs: Array<[number, number]> = [];\n userAgents.forEach((rawUserAgent, index) => {\n if (filter(rawUserAgent)) {\n weightIndexPairs.push([rawUserAgent.weight, index]);\n }\n });\n return makeCumulativeWeightIndexPairs(weightIndexPairs);\n};\n\nconst setCumulativeWeightIndexPairs = (\n userAgent: UserAgent,\n cumulativeWeightIndexPairs: Array<[number, number]>,\n) => {\n Object.defineProperty(userAgent, 'cumulativeWeightIndexPairs', {\n configurable: true,\n enumerable: false,\n writable: false,\n value: cumulativeWeightIndexPairs,\n });\n};\n\nexport class UserAgent extends Function {\n constructor(filters?: Filter) {\n super();\n setCumulativeWeightIndexPairs(this, constructCumulativeWeightIndexPairsFromFilters(filters));\n if (this.cumulativeWeightIndexPairs.length === 0) {\n throw new Error('No user agents matched your filters.');\n }\n\n this.randomize();\n\n // eslint-disable-next-line no-constructor-return\n return new Proxy(this, {\n apply: () => this.random(),\n get: (target, property, receiver) => {\n const dataCandidate =\n target.data &&\n typeof property === 'string' &&\n Object.prototype.hasOwnProperty.call(target.data, property) &&\n Object.prototype.propertyIsEnumerable.call(target.data, property);\n if (dataCandidate) {\n const value = target.data[property as keyof UserAgentData];\n if (value !== undefined) {\n return value;\n }\n }\n\n return Reflect.get(target, property, receiver);\n },\n });\n }\n\n static random = (filters: Filter) => {\n try {\n return new UserAgent(filters);\n } catch (error) {\n return null;\n }\n };\n\n //\n // Standard Object Methods\n //\n\n [Symbol.toPrimitive] = (): string => this.data.userAgent;\n\n toString = (): string => this.data.userAgent;\n\n random = (): UserAgent => {\n const userAgent = new UserAgent();\n setCumulativeWeightIndexPairs(userAgent, this.cumulativeWeightIndexPairs);\n userAgent.randomize();\n return userAgent;\n };\n\n randomize = (): void => {\n // Find a random raw random user agent.\n const randomNumber = Math.random();\n const [, index] =\n this.cumulativeWeightIndexPairs.find(\n ([cumulativeWeight]) => cumulativeWeight > randomNumber,\n ) ?? [];\n if (index == null) {\n throw new Error('Error finding a random user agent.');\n }\n const rawUserAgent = userAgents[index];\n\n (this as { data: UserAgentData }).data = cloneDeep(rawUserAgent);\n };\n}\n","import { Filter, UserAgent, UserAgentData } from './user-agent';\n\nexport default UserAgent;\nexport type { Filter, UserAgentData };\n"]}
1
+ {"version":3,"sources":["../src/user-agent.ts","../src/index.ts"],"names":["userAgents","untypedUserAgents","makeCumulativeWeightIndexPairs","weightIndexPairs","totalWeight","sum","weight","index","defaultWeightIndexPairs","defaultCumulativeWeightIndexPairs","constructFilter","filters","accessor","parentObject","childFilters","value","childFilter","key","valueFilter","constructCumulativeWeightIndexPairsFromFilters","filter","rawUserAgent","setCumulativeWeightIndexPairs","userAgent","cumulativeWeightIndexPairs","userAgentInstances","_a","_b","UserAgent","_UserAgent","count","pairs","entries","cumWeight","i","a","b","n","randomNumber","cumulativeWeight","target","proxy","_target","property","descriptor","instance","index_default"],"mappings":"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","file":"/home/circleci/user-agents/dist/index.cjs","sourcesContent":["import untypedUserAgents from './user-agents.json' with { type: 'json' };\n\nconst userAgents: UserAgentData[] = untypedUserAgents as UserAgentData[];\n\ntype NestedValueOf<T> = T extends object ? T[keyof T] | NestedValueOf<T[keyof T]> : T;\n\nexport type Filter<T extends UserAgentData | NestedValueOf<UserAgentData> = UserAgentData> =\n | ((parentObject: T) => boolean)\n | RegExp\n | Array<Filter<T>>\n | { [key: string]: Filter<T> }\n | string;\n\nexport interface UserAgentData {\n appName: 'Netscape';\n connection: {\n downlink: number;\n effectiveType: '3g' | '4g';\n rtt: number;\n downlinkMax?: number | null;\n type?: 'cellular' | 'wifi';\n };\n language?: string | null;\n oscpu?: string | null;\n platform:\n | 'iPad'\n | 'iPhone'\n | 'Linux aarch64'\n | 'Linux armv81'\n | 'Linux armv8l'\n | 'Linux x86_64'\n | 'MacIntel'\n | 'Win32';\n pluginsLength: number;\n screenHeight: number;\n screenWidth: number;\n userAgent: string;\n vendor: 'Apple Computer, Inc.' | 'Google Inc.' | '';\n weight: number;\n}\n\ndeclare module './user-agent' {\n export interface UserAgent extends Readonly<UserAgentData> {\n readonly cumulativeWeightIndexPairs: Array<[number, number]>;\n readonly data: UserAgentData;\n (): UserAgent;\n }\n}\n\n// Normalizes the total weight to 1 and constructs a cumulative distribution.\nconst makeCumulativeWeightIndexPairs = (\n weightIndexPairs: Array<[number, number]>,\n): Array<[number, number]> => {\n const totalWeight = weightIndexPairs.reduce((sum, [weight]) => sum + weight, 0);\n let sum = 0;\n return weightIndexPairs.map(([weight, index]) => {\n sum += weight / totalWeight;\n return [sum, index];\n });\n};\n\n// Precompute these so that we can quickly generate unfiltered user agents.\nconst defaultWeightIndexPairs: Array<[number, number]> = userAgents.map(({ weight }, index) => [\n weight,\n index,\n]);\nconst defaultCumulativeWeightIndexPairs = makeCumulativeWeightIndexPairs(defaultWeightIndexPairs);\n\n// Turn the various filter formats into a single filter function that acts on raw user agents.\nconst constructFilter = <T extends UserAgentData | NestedValueOf<UserAgentData>>(\n filters: Filter<T>,\n accessor: (parentObject: T) => T | NestedValueOf<T> = (parentObject: T): T => parentObject,\n): ((profile: T) => boolean) => {\n // WARNING: This type and a lot of the types in here are wrong, but I can't get TypeScript to\n // resolve things correctly so this will have to do for now.\n let childFilters: Array<(parentObject: T) => boolean>;\n if (typeof filters === 'function') {\n childFilters = [filters];\n } else if (filters instanceof RegExp) {\n childFilters = [\n (value: T | NestedValueOf<T>) =>\n typeof value === 'object' && value && 'userAgent' in value && value.userAgent\n ? filters.test(value.userAgent)\n : filters.test(value as string),\n ];\n } else if (filters instanceof Array) {\n childFilters = filters.map((childFilter) => constructFilter(childFilter));\n } else if (typeof filters === 'object') {\n childFilters = Object.entries(filters).map(([key, valueFilter]) =>\n constructFilter(\n valueFilter as Filter<T>,\n (parentObject: T): T | NestedValueOf<T> =>\n (parentObject as unknown as { [key: string]: NestedValueOf<T> })[key] as NestedValueOf<T>,\n ),\n );\n } else {\n childFilters = [\n (value: T | NestedValueOf<T>) =>\n typeof value === 'object' && value && 'userAgent' in value && value.userAgent\n ? filters === value.userAgent\n : filters === value,\n ];\n }\n\n return (parentObject: T) => {\n try {\n const value = accessor(parentObject);\n return childFilters.every((childFilter) => childFilter(value as T));\n } catch {\n // This happens when a user-agent lacks a nested property.\n return false;\n }\n };\n};\n\n// Construct normalized cumulative weight index pairs given the filters.\nconst constructCumulativeWeightIndexPairsFromFilters = (\n filters?: Filter<UserAgentData>,\n): Array<[number, number]> => {\n if (!filters) {\n return defaultCumulativeWeightIndexPairs;\n }\n\n const filter = constructFilter(filters);\n\n const weightIndexPairs: Array<[number, number]> = [];\n userAgents.forEach((rawUserAgent, index) => {\n if (filter(rawUserAgent)) {\n weightIndexPairs.push([rawUserAgent.weight, index]);\n }\n });\n return makeCumulativeWeightIndexPairs(weightIndexPairs);\n};\n\nconst setCumulativeWeightIndexPairs = (\n userAgent: UserAgent,\n cumulativeWeightIndexPairs: Array<[number, number]>,\n) => {\n Object.defineProperty(userAgent, 'cumulativeWeightIndexPairs', {\n configurable: true,\n enumerable: false,\n writable: false,\n value: cumulativeWeightIndexPairs,\n });\n};\n\n// WeakSet tracking all UserAgent instances for `instanceof` support through proxies.\nconst userAgentInstances = new WeakSet<object>();\n\nexport class UserAgent {\n static [Symbol.hasInstance](instance: unknown): boolean {\n return instance instanceof Object && userAgentInstances.has(instance as object);\n }\n\n static random = (filters: Filter) => {\n try {\n return new UserAgent(filters);\n } catch {\n return null;\n }\n };\n\n readonly data!: UserAgentData;\n\n constructor(filters?: Filter) {\n setCumulativeWeightIndexPairs(this, constructCumulativeWeightIndexPairsFromFilters(filters));\n if (this.cumulativeWeightIndexPairs.length === 0) {\n throw new Error('No user agents matched your filters.');\n }\n\n this.randomize();\n\n // Use a plain function as the proxy target so the `apply` trap works without\n // extending `Function`, which requires `eval` and violates CSP in browser extensions.\n // All property access is forwarded to the real UserAgent instance via the traps.\n const target = () => {};\n const proxy = new Proxy(target as unknown as this, {\n apply: () => this.random(),\n get: (_target, property) => {\n if (\n this.data &&\n typeof property === 'string' &&\n Object.prototype.hasOwnProperty.call(this.data, property) &&\n Object.prototype.propertyIsEnumerable.call(this.data, property)\n ) {\n const value = this.data[property as keyof UserAgentData];\n if (value !== undefined) {\n return value;\n }\n }\n\n return Reflect.get(this, property);\n },\n set: (_target, property, value) => Reflect.set(this, property, value),\n defineProperty: (_target, property, descriptor) =>\n Reflect.defineProperty(this, property, descriptor),\n getOwnPropertyDescriptor: (_target, property) =>\n Reflect.getOwnPropertyDescriptor(this, property),\n has: (_target, property) => Reflect.has(this, property),\n deleteProperty: (_target, property) => Reflect.deleteProperty(this, property),\n ownKeys: () => Reflect.ownKeys(this),\n getPrototypeOf: () => UserAgent.prototype,\n });\n userAgentInstances.add(proxy);\n return proxy;\n }\n\n [Symbol.toPrimitive] = (): string => this.data.userAgent;\n\n toString = (): string => this.data.userAgent;\n\n random = (): UserAgent => {\n const userAgent = new UserAgent();\n setCumulativeWeightIndexPairs(userAgent, this.cumulativeWeightIndexPairs);\n userAgent.randomize();\n return userAgent;\n };\n\n top = (count?: number): UserAgentData[] => {\n // Recover individual weights from the cumulative distribution and sort by descending weight.\n const pairs = this.cumulativeWeightIndexPairs;\n const entries = pairs.map(([cumWeight, index], i) => ({\n weight: i > 0 ? cumWeight - pairs[i - 1][0] : cumWeight,\n index,\n }));\n entries.sort((a, b) => b.weight - a.weight);\n const n = count != null ? Math.min(count, entries.length) : entries.length;\n return entries.slice(0, n).map(({ index }) => structuredClone(userAgents[index]));\n };\n\n randomize = (): void => {\n // Find a random raw random user agent.\n const randomNumber = Math.random();\n const [, index] =\n this.cumulativeWeightIndexPairs.find(\n ([cumulativeWeight]) => cumulativeWeight > randomNumber,\n ) ?? [];\n if (index == null) {\n throw new Error('Error finding a random user agent.');\n }\n\n (this as { data: UserAgentData }).data = structuredClone(userAgents[index]);\n };\n}\n","import { Filter, UserAgent, UserAgentData } from './user-agent';\n\nexport default UserAgent;\nexport type { Filter, UserAgentData };\n"]}
package/dist/index.d.cts CHANGED
@@ -28,13 +28,18 @@ declare module './user-agent' {
28
28
  (): UserAgent;
29
29
  }
30
30
  }
31
- declare class UserAgent extends Function {
32
- constructor(filters?: Filter);
31
+ declare class UserAgent {
32
+ static [Symbol.hasInstance](instance: unknown): boolean;
33
33
  static random: (filters: Filter) => UserAgent | null;
34
+ readonly data: UserAgentData;
35
+ constructor(filters?: Filter);
34
36
  [Symbol.toPrimitive]: () => string;
35
37
  toString: () => string;
36
38
  random: () => UserAgent;
39
+ top: (count?: number) => UserAgentData[];
37
40
  randomize: () => void;
38
41
  }
39
42
 
40
- export { Filter, UserAgentData, UserAgent as default };
43
+ // @ts-ignore
44
+ export = UserAgent;
45
+ export type { Filter, UserAgentData };
package/dist/index.d.ts CHANGED
@@ -28,13 +28,16 @@ declare module './user-agent' {
28
28
  (): UserAgent;
29
29
  }
30
30
  }
31
- declare class UserAgent extends Function {
32
- constructor(filters?: Filter);
31
+ declare class UserAgent {
32
+ static [Symbol.hasInstance](instance: unknown): boolean;
33
33
  static random: (filters: Filter) => UserAgent | null;
34
+ readonly data: UserAgentData;
35
+ constructor(filters?: Filter);
34
36
  [Symbol.toPrimitive]: () => string;
35
37
  toString: () => string;
36
38
  random: () => UserAgent;
39
+ top: (count?: number) => UserAgentData[];
37
40
  randomize: () => void;
38
41
  }
39
42
 
40
- export { Filter, UserAgentData, UserAgent as default };
43
+ export { type Filter, type UserAgentData, UserAgent as default };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import g from"lodash.clonedeep";import m from"./user-agents.json"assert{type:"json"};var o=m,d=t=>{let a=t.reduce((e,[n])=>e+n,0),r=0;return t.map(([e,n])=>(r+=e/a,[r,n]))},f=o.map(({weight:t},a)=>[t,a]),p=d(f),u=(t,a=r=>r)=>{let r;return typeof t=="function"?r=[t]:t instanceof RegExp?r=[e=>typeof e=="object"&&e&&"userAgent"in e&&e.userAgent?t.test(e.userAgent):t.test(e)]:t instanceof Array?r=t.map(e=>u(e)):typeof t=="object"?r=Object.entries(t).map(([e,n])=>u(n,s=>s[e])):r=[e=>typeof e=="object"&&e&&"userAgent"in e&&e.userAgent?t===e.userAgent:t===e],e=>{try{let n=a(e);return r.every(s=>s(n))}catch{return!1}}},A=t=>{if(!t)return p;let a=u(t),r=[];return o.forEach((e,n)=>{a(e)&&r.push([e.weight,n])}),d(r)},c=(t,a)=>{Object.defineProperty(t,"cumulativeWeightIndexPairs",{configurable:!0,enumerable:!1,writable:!1,value:a})},b,i=class t extends Function{constructor(r){super();this[b]=()=>this.data.userAgent;this.toString=()=>this.data.userAgent;this.random=()=>{let r=new t;return c(r,this.cumulativeWeightIndexPairs),r.randomize(),r};this.randomize=()=>{let r=Math.random(),[,e]=this.cumulativeWeightIndexPairs.find(([s])=>s>r)??[];if(e==null)throw new Error("Error finding a random user agent.");let n=o[e];this.data=g(n)};if(c(this,A(r)),this.cumulativeWeightIndexPairs.length===0)throw new Error("No user agents matched your filters.");return this.randomize(),new Proxy(this,{apply:()=>this.random(),get:(e,n,s)=>{if(e.data&&typeof n=="string"&&Object.prototype.hasOwnProperty.call(e.data,n)&&Object.prototype.propertyIsEnumerable.call(e.data,n)){let l=e.data[n];if(l!==void 0)return l}return Reflect.get(e,n,s)}})}static{b=Symbol.toPrimitive}static{this.random=r=>{try{return new t(r)}catch{return null}}}};var P=i;export{P as default};
1
+ import f from"./user-agents.json"with{type:"json"};var o=f,p=r=>{let n=r.reduce((e,[s])=>e+s,0),a=0;return r.map(([e,s])=>(a+=e/n,[a,s]))},y=o.map(({weight:r},n)=>[r,n]),b=p(y),l=(r,n=a=>a)=>{let a;return typeof r=="function"?a=[r]:r instanceof RegExp?a=[e=>typeof e=="object"&&e&&"userAgent"in e&&e.userAgent?r.test(e.userAgent):r.test(e)]:r instanceof Array?a=r.map(e=>l(e)):typeof r=="object"?a=Object.entries(r).map(([e,s])=>l(s,t=>t[e])):a=[e=>typeof e=="object"&&e&&"userAgent"in e&&e.userAgent?r===e.userAgent:r===e],e=>{try{let s=n(e);return a.every(t=>t(s))}catch{return!1}}},A=r=>{if(!r)return b;let n=l(r),a=[];return o.forEach((e,s)=>{n(e)&&a.push([e.weight,s])}),p(a)},g=(r,n)=>{Object.defineProperty(r,"cumulativeWeightIndexPairs",{configurable:!0,enumerable:!1,writable:!1,value:n})},d=new WeakSet,m,h,u=class r{constructor(n){this[m]=()=>this.data.userAgent;this.toString=()=>this.data.userAgent;this.random=()=>{let n=new r;return g(n,this.cumulativeWeightIndexPairs),n.randomize(),n};this.top=n=>{let a=this.cumulativeWeightIndexPairs,e=a.map(([t,i],c)=>({weight:c>0?t-a[c-1][0]:t,index:i}));e.sort((t,i)=>i.weight-t.weight);let s=n!=null?Math.min(n,e.length):e.length;return e.slice(0,s).map(({index:t})=>structuredClone(o[t]))};this.randomize=()=>{let n=Math.random(),[,a]=this.cumulativeWeightIndexPairs.find(([e])=>e>n)??[];if(a==null)throw new Error("Error finding a random user agent.");this.data=structuredClone(o[a])};if(g(this,A(n)),this.cumulativeWeightIndexPairs.length===0)throw new Error("No user agents matched your filters.");this.randomize();let a=()=>{},e=new Proxy(a,{apply:()=>this.random(),get:(s,t)=>{if(this.data&&typeof t=="string"&&Object.prototype.hasOwnProperty.call(this.data,t)&&Object.prototype.propertyIsEnumerable.call(this.data,t)){let i=this.data[t];if(i!==void 0)return i}return Reflect.get(this,t)},set:(s,t,i)=>Reflect.set(this,t,i),defineProperty:(s,t,i)=>Reflect.defineProperty(this,t,i),getOwnPropertyDescriptor:(s,t)=>Reflect.getOwnPropertyDescriptor(this,t),has:(s,t)=>Reflect.has(this,t),deleteProperty:(s,t)=>Reflect.deleteProperty(this,t),ownKeys:()=>Reflect.ownKeys(this),getPrototypeOf:()=>r.prototype});return d.add(e),e}static[(h=Symbol.hasInstance,m=Symbol.toPrimitive,h)](n){return n instanceof Object&&d.has(n)}static{this.random=n=>{try{return new r(n)}catch{return null}}}};var U=u;export{U as default};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/user-agent.ts","../src/index.ts"],"sourcesContent":["import cloneDeep from 'lodash.clonedeep';\n\nimport untypedUserAgents from './user-agents.json' assert { type: 'json' };\n\nconst userAgents: UserAgentData[] = untypedUserAgents as UserAgentData[];\n\ntype NestedValueOf<T> = T extends object ? T[keyof T] | NestedValueOf<T[keyof T]> : T;\n\nexport type Filter<T extends UserAgentData | NestedValueOf<UserAgentData> = UserAgentData> =\n | ((parentObject: T) => boolean)\n | RegExp\n | Array<Filter<T>>\n | { [key: string]: Filter<T> }\n | string;\n\nexport interface UserAgentData {\n appName: 'Netscape';\n connection: {\n downlink: number;\n effectiveType: '3g' | '4g';\n rtt: number;\n downlinkMax?: number | null;\n type?: 'cellular' | 'wifi';\n };\n language?: string | null;\n oscpu?: string | null;\n platform:\n | 'iPad'\n | 'iPhone'\n | 'Linux aarch64'\n | 'Linux armv81'\n | 'Linux armv8l'\n | 'Linux x86_64'\n | 'MacIntel'\n | 'Win32';\n pluginsLength: number;\n screenHeight: number;\n screenWidth: number;\n userAgent: string;\n vendor: 'Apple Computer, Inc.' | 'Google Inc.' | '';\n weight: number;\n}\n\ndeclare module './user-agent' {\n export interface UserAgent extends Readonly<UserAgentData> {\n readonly cumulativeWeightIndexPairs: Array<[number, number]>;\n readonly data: UserAgentData;\n (): UserAgent;\n }\n}\n\n// Normalizes the total weight to 1 and constructs a cumulative distribution.\nconst makeCumulativeWeightIndexPairs = (\n weightIndexPairs: Array<[number, number]>,\n): Array<[number, number]> => {\n const totalWeight = weightIndexPairs.reduce((sum, [weight]) => sum + weight, 0);\n let sum = 0;\n return weightIndexPairs.map(([weight, index]) => {\n sum += weight / totalWeight;\n return [sum, index];\n });\n};\n\n// Precompute these so that we can quickly generate unfiltered user agents.\nconst defaultWeightIndexPairs: Array<[number, number]> = userAgents.map(({ weight }, index) => [\n weight,\n index,\n]);\nconst defaultCumulativeWeightIndexPairs = makeCumulativeWeightIndexPairs(defaultWeightIndexPairs);\n\n// Turn the various filter formats into a single filter function that acts on raw user agents.\nconst constructFilter = <T extends UserAgentData | NestedValueOf<UserAgentData>>(\n filters: Filter<T>,\n accessor: (parentObject: T) => T | NestedValueOf<T> = (parentObject: T): T => parentObject,\n): ((profile: T) => boolean) => {\n // WARNING: This type and a lot of the types in here are wrong, but I can't get TypeScript to\n // resolve things correctly so this will have to do for now.\n let childFilters: Array<(parentObject: T) => boolean>;\n if (typeof filters === 'function') {\n childFilters = [filters];\n } else if (filters instanceof RegExp) {\n childFilters = [\n (value: T | NestedValueOf<T>) =>\n typeof value === 'object' && value && 'userAgent' in value && value.userAgent\n ? filters.test(value.userAgent)\n : filters.test(value as string),\n ];\n } else if (filters instanceof Array) {\n childFilters = filters.map((childFilter) => constructFilter(childFilter));\n } else if (typeof filters === 'object') {\n childFilters = Object.entries(filters).map(([key, valueFilter]) =>\n constructFilter(\n valueFilter as Filter<T>,\n (parentObject: T): T | NestedValueOf<T> =>\n (parentObject as unknown as { [key: string]: NestedValueOf<T> })[key] as NestedValueOf<T>,\n ),\n );\n } else {\n childFilters = [\n (value: T | NestedValueOf<T>) =>\n typeof value === 'object' && value && 'userAgent' in value && value.userAgent\n ? filters === value.userAgent\n : filters === value,\n ];\n }\n\n return (parentObject: T) => {\n try {\n const value = accessor(parentObject);\n return childFilters.every((childFilter) => childFilter(value as T));\n } catch (error) {\n // This happens when a user-agent lacks a nested property.\n return false;\n }\n };\n};\n\n// Construct normalized cumulative weight index pairs given the filters.\nconst constructCumulativeWeightIndexPairsFromFilters = (\n filters?: Filter<UserAgentData>,\n): Array<[number, number]> => {\n if (!filters) {\n return defaultCumulativeWeightIndexPairs;\n }\n\n const filter = constructFilter(filters);\n\n const weightIndexPairs: Array<[number, number]> = [];\n userAgents.forEach((rawUserAgent, index) => {\n if (filter(rawUserAgent)) {\n weightIndexPairs.push([rawUserAgent.weight, index]);\n }\n });\n return makeCumulativeWeightIndexPairs(weightIndexPairs);\n};\n\nconst setCumulativeWeightIndexPairs = (\n userAgent: UserAgent,\n cumulativeWeightIndexPairs: Array<[number, number]>,\n) => {\n Object.defineProperty(userAgent, 'cumulativeWeightIndexPairs', {\n configurable: true,\n enumerable: false,\n writable: false,\n value: cumulativeWeightIndexPairs,\n });\n};\n\nexport class UserAgent extends Function {\n constructor(filters?: Filter) {\n super();\n setCumulativeWeightIndexPairs(this, constructCumulativeWeightIndexPairsFromFilters(filters));\n if (this.cumulativeWeightIndexPairs.length === 0) {\n throw new Error('No user agents matched your filters.');\n }\n\n this.randomize();\n\n // eslint-disable-next-line no-constructor-return\n return new Proxy(this, {\n apply: () => this.random(),\n get: (target, property, receiver) => {\n const dataCandidate =\n target.data &&\n typeof property === 'string' &&\n Object.prototype.hasOwnProperty.call(target.data, property) &&\n Object.prototype.propertyIsEnumerable.call(target.data, property);\n if (dataCandidate) {\n const value = target.data[property as keyof UserAgentData];\n if (value !== undefined) {\n return value;\n }\n }\n\n return Reflect.get(target, property, receiver);\n },\n });\n }\n\n static random = (filters: Filter) => {\n try {\n return new UserAgent(filters);\n } catch (error) {\n return null;\n }\n };\n\n //\n // Standard Object Methods\n //\n\n [Symbol.toPrimitive] = (): string => this.data.userAgent;\n\n toString = (): string => this.data.userAgent;\n\n random = (): UserAgent => {\n const userAgent = new UserAgent();\n setCumulativeWeightIndexPairs(userAgent, this.cumulativeWeightIndexPairs);\n userAgent.randomize();\n return userAgent;\n };\n\n randomize = (): void => {\n // Find a random raw random user agent.\n const randomNumber = Math.random();\n const [, index] =\n this.cumulativeWeightIndexPairs.find(\n ([cumulativeWeight]) => cumulativeWeight > randomNumber,\n ) ?? [];\n if (index == null) {\n throw new Error('Error finding a random user agent.');\n }\n const rawUserAgent = userAgents[index];\n\n (this as { data: UserAgentData }).data = cloneDeep(rawUserAgent);\n };\n}\n","import { Filter, UserAgent, UserAgentData } from './user-agent';\n\nexport default UserAgent;\nexport type { Filter, UserAgentData };\n"],"mappings":"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","names":["cloneDeep","untypedUserAgents","userAgents","makeCumulativeWeightIndexPairs","weightIndexPairs","totalWeight","sum","weight","index","defaultWeightIndexPairs","defaultCumulativeWeightIndexPairs","constructFilter","filters","accessor","parentObject","childFilters","value","childFilter","key","valueFilter","constructCumulativeWeightIndexPairsFromFilters","filter","rawUserAgent","setCumulativeWeightIndexPairs","userAgent","cumulativeWeightIndexPairs","_a","UserAgent","_UserAgent","randomNumber","cumulativeWeight","target","property","receiver","src_default","UserAgent"]}
1
+ {"version":3,"sources":["../src/user-agent.ts","../src/index.ts"],"sourcesContent":["import untypedUserAgents from './user-agents.json' with { type: 'json' };\n\nconst userAgents: UserAgentData[] = untypedUserAgents as UserAgentData[];\n\ntype NestedValueOf<T> = T extends object ? T[keyof T] | NestedValueOf<T[keyof T]> : T;\n\nexport type Filter<T extends UserAgentData | NestedValueOf<UserAgentData> = UserAgentData> =\n | ((parentObject: T) => boolean)\n | RegExp\n | Array<Filter<T>>\n | { [key: string]: Filter<T> }\n | string;\n\nexport interface UserAgentData {\n appName: 'Netscape';\n connection: {\n downlink: number;\n effectiveType: '3g' | '4g';\n rtt: number;\n downlinkMax?: number | null;\n type?: 'cellular' | 'wifi';\n };\n language?: string | null;\n oscpu?: string | null;\n platform:\n | 'iPad'\n | 'iPhone'\n | 'Linux aarch64'\n | 'Linux armv81'\n | 'Linux armv8l'\n | 'Linux x86_64'\n | 'MacIntel'\n | 'Win32';\n pluginsLength: number;\n screenHeight: number;\n screenWidth: number;\n userAgent: string;\n vendor: 'Apple Computer, Inc.' | 'Google Inc.' | '';\n weight: number;\n}\n\ndeclare module './user-agent' {\n export interface UserAgent extends Readonly<UserAgentData> {\n readonly cumulativeWeightIndexPairs: Array<[number, number]>;\n readonly data: UserAgentData;\n (): UserAgent;\n }\n}\n\n// Normalizes the total weight to 1 and constructs a cumulative distribution.\nconst makeCumulativeWeightIndexPairs = (\n weightIndexPairs: Array<[number, number]>,\n): Array<[number, number]> => {\n const totalWeight = weightIndexPairs.reduce((sum, [weight]) => sum + weight, 0);\n let sum = 0;\n return weightIndexPairs.map(([weight, index]) => {\n sum += weight / totalWeight;\n return [sum, index];\n });\n};\n\n// Precompute these so that we can quickly generate unfiltered user agents.\nconst defaultWeightIndexPairs: Array<[number, number]> = userAgents.map(({ weight }, index) => [\n weight,\n index,\n]);\nconst defaultCumulativeWeightIndexPairs = makeCumulativeWeightIndexPairs(defaultWeightIndexPairs);\n\n// Turn the various filter formats into a single filter function that acts on raw user agents.\nconst constructFilter = <T extends UserAgentData | NestedValueOf<UserAgentData>>(\n filters: Filter<T>,\n accessor: (parentObject: T) => T | NestedValueOf<T> = (parentObject: T): T => parentObject,\n): ((profile: T) => boolean) => {\n // WARNING: This type and a lot of the types in here are wrong, but I can't get TypeScript to\n // resolve things correctly so this will have to do for now.\n let childFilters: Array<(parentObject: T) => boolean>;\n if (typeof filters === 'function') {\n childFilters = [filters];\n } else if (filters instanceof RegExp) {\n childFilters = [\n (value: T | NestedValueOf<T>) =>\n typeof value === 'object' && value && 'userAgent' in value && value.userAgent\n ? filters.test(value.userAgent)\n : filters.test(value as string),\n ];\n } else if (filters instanceof Array) {\n childFilters = filters.map((childFilter) => constructFilter(childFilter));\n } else if (typeof filters === 'object') {\n childFilters = Object.entries(filters).map(([key, valueFilter]) =>\n constructFilter(\n valueFilter as Filter<T>,\n (parentObject: T): T | NestedValueOf<T> =>\n (parentObject as unknown as { [key: string]: NestedValueOf<T> })[key] as NestedValueOf<T>,\n ),\n );\n } else {\n childFilters = [\n (value: T | NestedValueOf<T>) =>\n typeof value === 'object' && value && 'userAgent' in value && value.userAgent\n ? filters === value.userAgent\n : filters === value,\n ];\n }\n\n return (parentObject: T) => {\n try {\n const value = accessor(parentObject);\n return childFilters.every((childFilter) => childFilter(value as T));\n } catch {\n // This happens when a user-agent lacks a nested property.\n return false;\n }\n };\n};\n\n// Construct normalized cumulative weight index pairs given the filters.\nconst constructCumulativeWeightIndexPairsFromFilters = (\n filters?: Filter<UserAgentData>,\n): Array<[number, number]> => {\n if (!filters) {\n return defaultCumulativeWeightIndexPairs;\n }\n\n const filter = constructFilter(filters);\n\n const weightIndexPairs: Array<[number, number]> = [];\n userAgents.forEach((rawUserAgent, index) => {\n if (filter(rawUserAgent)) {\n weightIndexPairs.push([rawUserAgent.weight, index]);\n }\n });\n return makeCumulativeWeightIndexPairs(weightIndexPairs);\n};\n\nconst setCumulativeWeightIndexPairs = (\n userAgent: UserAgent,\n cumulativeWeightIndexPairs: Array<[number, number]>,\n) => {\n Object.defineProperty(userAgent, 'cumulativeWeightIndexPairs', {\n configurable: true,\n enumerable: false,\n writable: false,\n value: cumulativeWeightIndexPairs,\n });\n};\n\n// WeakSet tracking all UserAgent instances for `instanceof` support through proxies.\nconst userAgentInstances = new WeakSet<object>();\n\nexport class UserAgent {\n static [Symbol.hasInstance](instance: unknown): boolean {\n return instance instanceof Object && userAgentInstances.has(instance as object);\n }\n\n static random = (filters: Filter) => {\n try {\n return new UserAgent(filters);\n } catch {\n return null;\n }\n };\n\n readonly data!: UserAgentData;\n\n constructor(filters?: Filter) {\n setCumulativeWeightIndexPairs(this, constructCumulativeWeightIndexPairsFromFilters(filters));\n if (this.cumulativeWeightIndexPairs.length === 0) {\n throw new Error('No user agents matched your filters.');\n }\n\n this.randomize();\n\n // Use a plain function as the proxy target so the `apply` trap works without\n // extending `Function`, which requires `eval` and violates CSP in browser extensions.\n // All property access is forwarded to the real UserAgent instance via the traps.\n const target = () => {};\n const proxy = new Proxy(target as unknown as this, {\n apply: () => this.random(),\n get: (_target, property) => {\n if (\n this.data &&\n typeof property === 'string' &&\n Object.prototype.hasOwnProperty.call(this.data, property) &&\n Object.prototype.propertyIsEnumerable.call(this.data, property)\n ) {\n const value = this.data[property as keyof UserAgentData];\n if (value !== undefined) {\n return value;\n }\n }\n\n return Reflect.get(this, property);\n },\n set: (_target, property, value) => Reflect.set(this, property, value),\n defineProperty: (_target, property, descriptor) =>\n Reflect.defineProperty(this, property, descriptor),\n getOwnPropertyDescriptor: (_target, property) =>\n Reflect.getOwnPropertyDescriptor(this, property),\n has: (_target, property) => Reflect.has(this, property),\n deleteProperty: (_target, property) => Reflect.deleteProperty(this, property),\n ownKeys: () => Reflect.ownKeys(this),\n getPrototypeOf: () => UserAgent.prototype,\n });\n userAgentInstances.add(proxy);\n return proxy;\n }\n\n [Symbol.toPrimitive] = (): string => this.data.userAgent;\n\n toString = (): string => this.data.userAgent;\n\n random = (): UserAgent => {\n const userAgent = new UserAgent();\n setCumulativeWeightIndexPairs(userAgent, this.cumulativeWeightIndexPairs);\n userAgent.randomize();\n return userAgent;\n };\n\n top = (count?: number): UserAgentData[] => {\n // Recover individual weights from the cumulative distribution and sort by descending weight.\n const pairs = this.cumulativeWeightIndexPairs;\n const entries = pairs.map(([cumWeight, index], i) => ({\n weight: i > 0 ? cumWeight - pairs[i - 1][0] : cumWeight,\n index,\n }));\n entries.sort((a, b) => b.weight - a.weight);\n const n = count != null ? Math.min(count, entries.length) : entries.length;\n return entries.slice(0, n).map(({ index }) => structuredClone(userAgents[index]));\n };\n\n randomize = (): void => {\n // Find a random raw random user agent.\n const randomNumber = Math.random();\n const [, index] =\n this.cumulativeWeightIndexPairs.find(\n ([cumulativeWeight]) => cumulativeWeight > randomNumber,\n ) ?? [];\n if (index == null) {\n throw new Error('Error finding a random user agent.');\n }\n\n (this as { data: UserAgentData }).data = structuredClone(userAgents[index]);\n };\n}\n","import { Filter, UserAgent, UserAgentData } from './user-agent';\n\nexport default UserAgent;\nexport type { Filter, UserAgentData };\n"],"mappings":"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","names":["untypedUserAgents","userAgents","makeCumulativeWeightIndexPairs","weightIndexPairs","totalWeight","sum","weight","index","defaultWeightIndexPairs","defaultCumulativeWeightIndexPairs","constructFilter","filters","accessor","parentObject","childFilters","value","childFilter","key","valueFilter","constructCumulativeWeightIndexPairsFromFilters","filter","rawUserAgent","setCumulativeWeightIndexPairs","userAgent","cumulativeWeightIndexPairs","userAgentInstances","_a","_b","UserAgent","_UserAgent","count","pairs","entries","cumWeight","i","a","b","n","randomNumber","cumulativeWeight","target","proxy","_target","property","descriptor","instance","index_default","UserAgent"]}