Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 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 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | 10x 10x 10x 10x 10x 10x 80x 147x 66x 66x 144x 2x 142x 1x 3x 3x 141x 66x 66x 66x 67x 46x 2x 18x 1x 10x 68x 68x 68x 55x 54x 1x 67x 67x 3x 67x 66x 66x 66x | import { ExtractQueryParams, Region } from './types' import { version } from '../package.json' import { paths } from './generatedApiTypes' const euRegionUrl = 'https://eu.api.fpjs.io/' const apRegionUrl = 'https://ap.api.fpjs.io/' const globalRegionUrl = 'https://api.fpjs.io/' type QueryStringScalar = string | number | boolean | null | undefined type QueryStringParameters = Record<string, QueryStringScalar | string[]> & { api_key?: string ii: string } export function getIntegrationInfo() { return `fingerprint-pro-server-node-sdk/${version}` } function isEmptyValue(value: any): boolean { return value === undefined || value === null } function serializeQueryStringParams(params: QueryStringParameters): string { const entries: [string, string][] = [] for (const [key, value] of Object.entries(params)) { // Use the helper for the main value if (isEmptyValue(value)) { continue } if (Array.isArray(value)) { for (const v of value) { // Also use the helper for each item in the array Iif (isEmptyValue(v)) { continue } entries.push([`${key}[]`, String(v)]) } } else { entries.push([key, String(value)]) } } Iif (!entries.length) { return '' } const urlSearchParams = new URLSearchParams(entries) return urlSearchParams.toString() } function getServerApiUrl(region: Region): string { switch (region) { case Region.EU: return euRegionUrl case Region.AP: return apRegionUrl case Region.Global: return globalRegionUrl default: throw new Error('Unsupported region') } } /** * Extracts parameter placeholders into a literal union type. * For example `extractPathParams<'/users/{userId}/posts/{postId}'>` resolves to `"userId" | "postId" */ type ExtractPathParams<T extends string> = T extends `${string}{${infer Param}}${infer Rest}` ? Param | ExtractPathParams<Rest> : never type PathParams<Path extends keyof paths> = ExtractPathParams<Path> extends never ? { pathParams?: never } : { pathParams: ExtractPathParams<Path> extends never ? never : string[] } type QueryParams<Path extends keyof paths, Method extends keyof paths[Path]> = ExtractQueryParams<paths[Path][Method]> extends never ? { queryParams?: any } // No query params : { queryParams?: ExtractQueryParams<paths[Path][Method]> // Optional query params } type GetRequestPathOptions<Path extends keyof paths, Method extends keyof paths[Path]> = { path: Path method: Method apiKey?: string region: Region } & PathParams<Path> & QueryParams<Path, Method> /** * Formats a URL for the FingerprintJS server API by replacing placeholders and * appending query string parameters. * * @internal * * @param {GetRequestPathOptions<Path, Method>} options * @param {Path} options.path - The path of the API endpoint * @param {string[]} [options.pathParams] - Path parameters to be replaced in the path * @param {string} [options.apiKey] - API key to be included in the query string * @param {QueryParams<Path, Method>["queryParams"]} [options.queryParams] - Query string * parameters to be appended to the URL * @param {Region} options.region - The region of the API endpoint * @param {Method} options.method - The method of the API endpoint * * @returns {string} The formatted URL with parameters replaced and query string * parameters appended */ export function getRequestPath<Path extends keyof paths, Method extends keyof paths[Path]>({ path, pathParams, apiKey, queryParams, region, // method mention here so that it can be referenced in JSDoc // eslint-disable-next-line @typescript-eslint/no-unused-vars method: _, }: GetRequestPathOptions<Path, Method>): string { // Step 1: Extract the path parameters (placeholders) from the path const placeholders = Array.from(path.matchAll(/{(.*?)}/g)).map((match) => match[1]) // Step 2: Replace the placeholders with provided pathParams let formattedPath: string = path placeholders.forEach((placeholder, index) => { if (pathParams?.[index]) { formattedPath = formattedPath.replace(`{${placeholder}}`, pathParams[index]) } else { throw new Error(`Missing path parameter for ${placeholder}`) } }) const queryStringParameters: QueryStringParameters = { ...(queryParams ?? {}), ii: getIntegrationInfo(), } if (apiKey) { queryStringParameters.api_key = apiKey } const url = new URL(getServerApiUrl(region)) url.pathname = formattedPath url.search = serializeQueryStringParams(queryStringParameters) return url.toString() } |