@vercel/flags
Version:
Flags SDK by Vercel - The feature flags toolkit for Next.js and SvelteKit
173 lines (158 loc) • 6.17 kB
JavaScript
;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; }
var _chunkAVMIIWOFcjs = require('./chunk-AVMIIWOF.cjs');
var _chunkJYRFFBKMcjs = require('./chunk-JYRFFBKM.cjs');
var _chunkMEG7RDX7cjs = require('./chunk-MEG7RDX7.cjs');
// src/sveltekit/index.ts
var _async_hooks = require('async_hooks');
var _cookies = require('@edge-runtime/cookies');
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 = _chunkJYRFFBKMcjs.HeadersAdapter.seal(headers);
headersMap.set(headers, sealed);
return sealed;
}
function sealCookies(headers) {
const cached = cookiesMap.get(headers);
if (cached !== void 0)
return cached;
const sealed = _chunkJYRFFBKMcjs.RequestCookiesAdapter.seal(new (0, _cookies.RequestCookies)(headers));
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(
`@vercel/flags: No decide function provided for ${definition.key}`
);
};
}
function flag(definition) {
const decide = getDecide(definition);
const flagImpl = async function flagImpl2() {
const store = flagStorage.getStore();
if (!store) {
throw new Error("@vercel/flags: context not found");
}
if (hasOwnProperty(store.usedFlags, definition.key)) {
const valuePromise2 = store.usedFlags[definition.key];
if (typeof valuePromise2 !== "undefined") {
return valuePromise2;
}
}
const overridesCookie = store.event.cookies.get("vercel-flag-overrides");
const overrides = overridesCookie ? await _chunkJYRFFBKMcjs.decrypt.call(void 0, overridesCookie, store.secret) : void 0;
if (overrides && hasOwnProperty(overrides, definition.key)) {
const value2 = overrides[definition.key];
if (typeof value2 !== "undefined") {
_chunkJYRFFBKMcjs.reportValue.call(void 0, definition.key, value2);
store.usedFlags[definition.key] = Promise.resolve(value2);
return value2;
}
}
const valuePromise = decide(
{
headers: sealHeaders(store.event.request.headers),
cookies: sealCookies(store.event.request.headers)
},
// @ts-expect-error not part of the type, but we supply it for convenience
{ event: store.event }
);
store.usedFlags[definition.key] = valuePromise;
const value = await valuePromise;
_chunkJYRFFBKMcjs.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 = definition.options;
flagImpl.decide = decide;
return flagImpl;
}
function getProviderData(flags) {
const definitions = Object.values(flags).reduce(
(acc, d) => {
acc[d.key] = {
options: _chunkAVMIIWOFcjs.normalizeOptions.call(void 0, d.options),
origin: d.origin,
description: d.description
};
return acc;
},
{}
);
return { definitions, hints: [] };
}
function createContext(event, secret) {
return {
event,
secret,
usedFlags: {}
};
}
var flagStorage = new (0, _async_hooks.AsyncLocalStorage)();
function createHandle({
secret,
flags
}) {
return function handle({ event, resolve }) {
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, secret);
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 _chunkJYRFFBKMcjs.encrypt.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 _chunkJYRFFBKMcjs.verifyAccess.call(void 0,
event.request.headers.get("Authorization"),
secret
);
if (!access)
return new Response(null, { status: 401 });
return Response.json(getProviderData(flags));
}
exports.createHandle = createHandle; exports.flag = flag; exports.getProviderData = getProviderData;
//# sourceMappingURL=sveltekit.cjs.map