UNPKG

flags

Version:

Flags SDK by Vercel - The feature flags toolkit for Next.js and SvelteKit

164 lines (156 loc) 6.1 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/lib/normalize-options.ts function normalizeOptions(flagOptions) { if (!Array.isArray(flagOptions)) return flagOptions; return flagOptions.map((option) => { if (typeof option === "boolean") return { value: option }; if (typeof option === "number") return { value: option }; if (typeof option === "string") return { value: option }; if (option === null) return { value: option }; return option; }); } // src/lib/async-memoize-one.ts function memoizeOne(fn, isEqual, { cachePromiseRejection = false } = {}) { let calledOnce = false; let oldArgs; let lastResult; function memoized(...newArgs) { if (calledOnce && isEqual(newArgs, oldArgs)) return lastResult; lastResult = fn.apply(this, newArgs); if (!cachePromiseRejection && lastResult.catch) { lastResult.catch(() => calledOnce = false); } calledOnce = true; oldArgs = newArgs; return lastResult; } return memoized; } // src/lib/serialization.ts var _jose = require('jose'); var memoizedVerify = memoizeOne( (code, secret) => _jose.compactVerify.call(void 0, code, _jose.base64url.decode(secret), { algorithms: ["HS256"] }), (a, b) => a[0] === b[0] && a[1] === b[1], // only first two args matter { cachePromiseRejection: true } ); var memoizedSign = memoizeOne( (uint8Array, secret) => new (0, _jose.CompactSign)(uint8Array).setProtectedHeader({ alg: "HS256" }).sign(_jose.base64url.decode(secret)), (a, b) => ( // matchedIndices array must be equal a[0].length === b[0].length && a[0].every((v, i) => b[0][i] === v) && // secrets must be equal a[1] === b[1] ), { cachePromiseRejection: true } ); function splitUint8Array(array, index) { const firstHalf = array.slice(0, index); const secondHalf = array.slice(index); return [firstHalf, secondHalf]; } async function deserialize(code, flags, secret) { const { payload } = await memoizedVerify(code, secret); const [matchedIndicesArray, valuesUint8Array] = payload.length === flags.length ? [payload] : splitUint8Array(payload, flags.length); const valuesArray = valuesUint8Array ? ( // re-add opening and closing brackets since we remove them when serializing JSON.parse(`[${new TextDecoder().decode(valuesUint8Array)}]`) ) : null; let spilled = 0; return matchedIndicesArray.reduce( (acc, valueIndex, index) => { const flag = flags[index]; if (!flag) { throw new Error(`flags: No flag at index ${index}`); } switch (valueIndex) { case 253 /* BOOLEAN_FALSE */: acc[flag.key] = false; break; case 254 /* BOOLEAN_TRUE */: acc[flag.key] = true; break; case 255 /* UNLISTED_VALUE */: acc[flag.key] = valuesArray[spilled++]; break; case 252 /* NULL */: acc[flag.key] = null; break; default: acc[flag.key] = _optionalChain([flag, 'access', _ => _.options, 'optionalAccess', _2 => _2[valueIndex], 'optionalAccess', _3 => _3.value]); } return acc; }, {} ); } var matchIndex = /* @__PURE__ */ function() { const stringifiedOptionsCache = /* @__PURE__ */ new Map(); return function matchIndex2(options, value) { const t = typeof value; if (value === null || t === "boolean" || t === "string" || t === "number") { return options.findIndex((v) => v.value === value); } const stringifiedValue = JSON.stringify(value); let stringifiedOptions = stringifiedOptionsCache.get(options); if (!stringifiedOptions) { stringifiedOptions = options.map((o) => JSON.stringify(o.value)); stringifiedOptionsCache.set(options, stringifiedOptions); } return stringifiedOptions.findIndex( (stringifiedOption) => stringifiedOption === stringifiedValue ); }; }(); function joinUint8Arrays(array1, array2) { const combined = new Uint8Array(array1.length + array2.length); combined.set(array1); combined.set(array2, array1.length); return combined; } async function serialize(flagSet, flags, secret) { const unlistedValues = []; const matchedIndices = new Uint8Array( flags.map((flag) => { const options = Array.isArray(flag.options) ? flag.options : []; const value = flagSet[flag.key]; if (!Object.prototype.hasOwnProperty.call(flagSet, flag.key) || value === void 0) { throw new Error(`flags: Missing value for flag "${flag.key}"`); } switch (value) { case null: return 252 /* NULL */; case false: return 253 /* BOOLEAN_FALSE */; case true: return 254 /* BOOLEAN_TRUE */; } const matchedIndex = matchIndex(options, value); if (matchedIndex > -1) return matchedIndex; unlistedValues.push(value); return 255 /* UNLISTED_VALUE */; }) ); let joined; if (unlistedValues.length > 0) { const jsonArray = new TextEncoder().encode( // slicing removes opening and closing array brackets as they'll always be // there and we can re-add them when deserializing JSON.stringify(unlistedValues).slice(1, -1) ); joined = joinUint8Arrays(matchedIndices, jsonArray); } else { joined = matchedIndices; } return memoizedSign(joined, secret); } exports.memoizeOne = memoizeOne; exports.normalizeOptions = normalizeOptions; exports.deserialize = deserialize; exports.serialize = serialize; //# sourceMappingURL=chunk-QLJ65HXQ.cjs.map