UNPKG

@web-widget/flags-kit

Version:

Flags SDK by Vercel - The feature flags toolkit for Next.js, SvelteKit, and Web Router - Enhanced fork with improved Web Router support

353 lines (316 loc) 13.2 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } 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; } var _chunkQLJ65HXQcjs = require('./chunk-QLJ65HXQ.cjs'); var _chunkROBQSGBHcjs = require('./chunk-ROBQSGBH.cjs'); var _chunkMEG7RDX7cjs = require('./chunk-MEG7RDX7.cjs'); // src/sveltekit/index.ts var _kit = require('@sveltejs/kit'); var _async_hooks = require('async_hooks'); var _cookies = require('@edge-runtime/cookies'); // src/sveltekit/precompute.ts async function evaluate(flags, request) { return Promise.all(flags.map((flag2) => flag2(request))); } async function precompute(flags, request, secret) { const values = await evaluate(flags, request); return serialize2(flags, values, secret); } function combine(flags, values) { return Object.fromEntries(flags.map((flag2, i) => [flag2.key, values[i]])); } async function serialize2(flags, values, secret) { return _chunkQLJ65HXQcjs.serialize.call(void 0, combine(flags, values), flags, secret); } async function deserialize2(flags, code, secret) { return _chunkQLJ65HXQcjs.deserialize.call(void 0, code, flags, secret); } async function getPrecomputed(flagKey, precomputeFlags, code, secret) { const flagSet = await deserialize2(precomputeFlags, code, secret); return flagSet[flagKey]; } function* cartesianIterator(items) { const remainder = items.length > 1 ? cartesianIterator(items.slice(1)) : [[]]; for (let r of remainder) for (let h of items.at(0)) yield [h, ...r]; } async function generatePermutations(flags, filter = null, secret) { const options = flags.map((flag2) => { if (!flag2.options) return [false, true]; return flag2.options.map((option) => option.value); }); const list = []; for (const permutation of cartesianIterator(options)) { const permObject = permutation.reduce( (acc, value, index) => { acc[flags[index].key] = value; return acc; }, {} ); if (!filter || filter(permObject)) list.push(permObject); } return Promise.all(list.map((values) => _chunkQLJ65HXQcjs.serialize.call(void 0, values, flags, secret))); } // src/sveltekit/env.ts var default_secret = process.env.FLAGS_SECRET; async function tryGetSecret(secret) { if (!default_secret) { try { const env = await Promise.resolve().then(() => _interopRequireWildcard(require("$env/static/private"))); default_secret = env.FLAGS_SECRET; } catch (e) { } } secret = secret || default_secret; if (!secret) { throw new Error( "flags: No secret provided. Set an environment variable FLAGS_SECRET or provide a secret to the function." ); } return secret; } // src/sveltekit/index.ts function hasOwnProperty(obj, prop) { return obj.hasOwnProperty(prop); } var headersMap = /* @__PURE__ */ new WeakMap(); var cookiesMap = /* @__PURE__ */ new WeakMap(); function sealHeaders(headers) { const cached = headersMap.get(headers); if (cached !== void 0) return cached; const sealed = _chunkROBQSGBHcjs.HeadersAdapter.seal( headers, "Headers cannot be modified in SvelteKit. Headers are read-only during request processing." ); headersMap.set(headers, sealed); return sealed; } function sealCookies(headers) { const cached = cookiesMap.get(headers); if (cached !== void 0) return cached; const sealed = _chunkROBQSGBHcjs.RequestCookiesAdapter.seal( new (0, _cookies.RequestCookies)(headers), "Cookies cannot be modified in SvelteKit. Use the cookies API from @sveltejs/kit to set cookies. Read more: https://kit.svelte.dev/docs/load#cookies" ); cookiesMap.set(headers, sealed); return sealed; } async function resolveObjectPromises(obj) { const entries = Object.entries(obj); const resolvedEntries = await Promise.all( entries.map(async ([key, promise]) => { const value = await promise; return [key, value]; }) ); return Object.fromEntries(resolvedEntries); } function getDecide(definition) { return function decide(params) { if (typeof definition.decide === "function") { return definition.decide(params); } if (typeof _optionalChain([definition, 'access', _ => _.adapter, 'optionalAccess', _2 => _2.decide]) === "function") { return definition.adapter.decide({ key: definition.key, ...params }); } throw new Error(`flags: No decide function provided for ${definition.key}`); }; } function getIdentify(definition) { if (typeof definition.identify === "function") { return definition.identify; } if (typeof _optionalChain([definition, 'access', _3 => _3.adapter, 'optionalAccess', _4 => _4.identify]) === "function") { return definition.adapter.identify; } } var requestMap = /* @__PURE__ */ new WeakMap(); function flag(definition) { const decide = getDecide(definition); const identify = getIdentify(definition); const flagImpl = async function flagImpl2(requestOrCode, flagsArrayOrSecret) { let store = flagStorage.getStore(); if (!store) { if (requestOrCode instanceof Request) { store = requestMap.get(requestOrCode); if (!store) { store = createContext( requestOrCode, await _asyncNullishCoalesce(flagsArrayOrSecret, async () => ( await tryGetSecret())) ); requestMap.set(requestOrCode, store); } } else { throw new Error("flags: Neither context found nor Request provided"); } } if (typeof requestOrCode === "string" && Array.isArray(flagsArrayOrSecret)) { return getPrecomputed( definition.key, flagsArrayOrSecret, requestOrCode, store.secret ); } if (hasOwnProperty(store.usedFlags, definition.key)) { const valuePromise2 = store.usedFlags[definition.key]; if (typeof valuePromise2 !== "undefined") { return valuePromise2; } } const headers = sealHeaders(store.request.headers); const cookies = sealCookies(store.request.headers); const overridesCookie = _optionalChain([cookies, 'access', _5 => _5.get, 'call', _6 => _6("vercel-flag-overrides"), 'optionalAccess', _7 => _7.value]); const overrides = overridesCookie ? await _chunkROBQSGBHcjs.decryptOverrides.call(void 0, overridesCookie, store.secret) : void 0; if (overrides && hasOwnProperty(overrides, definition.key)) { const value2 = overrides[definition.key]; if (typeof value2 !== "undefined") { _chunkROBQSGBHcjs.reportValue.call(void 0, definition.key, value2); store.usedFlags[definition.key] = Promise.resolve(value2); return value2; } } let entities; if (identify) { if (!store.identifiers.has(identify)) { const entities2 = identify({ headers, cookies }); store.identifiers.set(identify, entities2); } entities = await store.identifiers.get(identify); } const valuePromise = decide({ headers, cookies, entities }); store.usedFlags[definition.key] = valuePromise; const value = await valuePromise; _chunkROBQSGBHcjs.reportValue.call(void 0, definition.key, value); return value; }; flagImpl.key = definition.key; flagImpl.defaultValue = definition.defaultValue; flagImpl.origin = definition.origin; flagImpl.description = definition.description; flagImpl.options = _chunkQLJ65HXQcjs.normalizeOptions.call(void 0, definition.options); flagImpl.decide = decide; flagImpl.identify = identify; return flagImpl; } function getProviderData(flags) { const definitions = Object.values(flags).reduce( (acc, d) => { acc[d.key] = { options: _chunkQLJ65HXQcjs.normalizeOptions.call(void 0, d.options), origin: d.origin, description: d.description }; return acc; }, {} ); return { definitions, hints: [] }; } function createContext(request, secret, params) { return { request, secret, params: _nullishCoalesce(params, () => ( {})), usedFlags: {}, identifiers: /* @__PURE__ */ new Map() }; } var flagStorage = new (0, _async_hooks.AsyncLocalStorage)(); function createHandle({ secret, flags }) { return async function handle({ event, resolve }) { await _asyncNullishCoalesce(secret, async () => ( (secret = await tryGetSecret(secret)))); if (flags && // avoid creating the URL object for every request by checking with includes() first event.request.url.includes("/.well-known/") && new URL(event.request.url).pathname === "/.well-known/vercel/flags") { return handleWellKnownFlagsRoute(event, secret, flags); } const flagContext = createContext( event.request, secret, event.params ); return flagStorage.run( flagContext, () => resolve(event, { transformPageChunk: async ({ html }) => { const store = flagStorage.getStore(); if (!store || Object.keys(store.usedFlags).length === 0) return html; const encryptedFlagValues = await _chunkROBQSGBHcjs.encryptFlagValues.call(void 0, await resolveObjectPromises(store.usedFlags), secret ); return html.replace( "</body>", `<script type="application/json" data-flag-values>${_chunkMEG7RDX7cjs.safeJsonStringify.call(void 0, encryptedFlagValues)}</script></body>` ); } }) ); }; } async function handleWellKnownFlagsRoute(event, secret, flags) { const access = await _chunkROBQSGBHcjs.verifyAccess.call(void 0, event.request.headers.get("Authorization"), secret ); if (!access) return new Response(null, { status: 401 }); const providerData = getProviderData(flags); return Response.json(providerData, { headers: { "x-flags-sdk-version": _chunkROBQSGBHcjs.version } }); } async function encryptFlagValues2(value, secret) { return _chunkROBQSGBHcjs.encryptFlagValues.call(void 0, value, await tryGetSecret(secret)); } async function decryptFlagValues2(encryptedData, secret) { return _chunkROBQSGBHcjs.decryptFlagValues.call(void 0, encryptedData, await tryGetSecret(secret)); } async function encryptOverrides2(overrides, secret) { return _chunkROBQSGBHcjs.encryptOverrides.call(void 0, overrides, await tryGetSecret(secret)); } async function decryptOverrides2(encryptedData, secret) { return _chunkROBQSGBHcjs.decryptOverrides.call(void 0, encryptedData, await tryGetSecret(secret)); } async function encryptFlagDefinitions2(value, secret) { return _chunkROBQSGBHcjs.encryptFlagDefinitions.call(void 0, value, await tryGetSecret(secret)); } async function decryptFlagDefinitions2(encryptedData, secret) { return _chunkROBQSGBHcjs.decryptFlagDefinitions.call(void 0, encryptedData, await tryGetSecret(secret)); } async function precompute2(flags, request, secret) { return precompute(flags, request, await tryGetSecret(secret)); } async function generatePermutations2(flags, filter = null, secret) { return generatePermutations(flags, filter, await tryGetSecret(secret)); } function createFlagsDiscoveryEndpoint(getApiData, options) { const requestHandler = async (event) => { const access = await _chunkROBQSGBHcjs.verifyAccess.call(void 0, event.request.headers.get("Authorization"), _optionalChain([options, 'optionalAccess', _8 => _8.secret]) ); if (!access) _kit.error.call(void 0, 401); const apiData = await getApiData(event); return _kit.json.call(void 0, apiData, { headers: { "x-flags-sdk-version": _chunkROBQSGBHcjs.version } }); }; return requestHandler; } exports.createFlagsDiscoveryEndpoint = createFlagsDiscoveryEndpoint; exports.createHandle = createHandle; exports.decryptFlagDefinitions = decryptFlagDefinitions2; exports.decryptFlagValues = decryptFlagValues2; exports.decryptOverrides = decryptOverrides2; exports.encryptFlagDefinitions = encryptFlagDefinitions2; exports.encryptFlagValues = encryptFlagValues2; exports.encryptOverrides = encryptOverrides2; exports.flag = flag; exports.generatePermutations = generatePermutations2; exports.getProviderData = getProviderData; exports.precompute = precompute2; //# sourceMappingURL=sveltekit.cjs.map