@flagsync/nextjs-sdk 0.8.6-alpha.1 → 0.8.6-alpha.3
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/dist/index.cjs +24 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +24 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -38,21 +38,42 @@ function getClientCache() {
|
|
|
38
38
|
store[CLIENT_CACHE_KEY] ??= /* @__PURE__ */ new Map();
|
|
39
39
|
return store[CLIENT_CACHE_KEY];
|
|
40
40
|
}
|
|
41
|
+
function fingerprintConfig(config) {
|
|
42
|
+
try {
|
|
43
|
+
return JSON.stringify(config);
|
|
44
|
+
} catch {
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
41
48
|
function createClient(config) {
|
|
42
49
|
const cache = getClientCache();
|
|
43
50
|
const existing = cache.get(config.sdkKey);
|
|
44
51
|
if (existing) {
|
|
45
|
-
|
|
52
|
+
if (process.env.NODE_ENV !== "production" && existing.configFingerprint !== fingerprintConfig(config)) {
|
|
53
|
+
console.warn(
|
|
54
|
+
"***************************************************************"
|
|
55
|
+
);
|
|
56
|
+
console.warn(
|
|
57
|
+
"[flagsync] createClient was called with a changed config, but a client for this SDK key already exists and will be reused. Restart the dev server to apply the new config."
|
|
58
|
+
);
|
|
59
|
+
console.warn(
|
|
60
|
+
"***************************************************************"
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return existing.client;
|
|
46
64
|
}
|
|
47
65
|
const instance = (0, import_node_sdk.FlagSyncFactory)({
|
|
48
66
|
...config,
|
|
49
67
|
metadata: {
|
|
50
68
|
sdkName: "@flagsync/nextjs-sdk",
|
|
51
|
-
sdkVersion: "0.8.6-alpha.
|
|
69
|
+
sdkVersion: "0.8.6-alpha.3"
|
|
52
70
|
}
|
|
53
71
|
});
|
|
54
72
|
const client = instance.client();
|
|
55
|
-
cache.set(config.sdkKey,
|
|
73
|
+
cache.set(config.sdkKey, {
|
|
74
|
+
client,
|
|
75
|
+
configFingerprint: fingerprintConfig(config)
|
|
76
|
+
});
|
|
56
77
|
return client;
|
|
57
78
|
}
|
|
58
79
|
function createAdapter(client) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/identify.ts"],"sourcesContent":["export type {\n CustomAttributes,\n CustomAttributeValue,\n FsConfig,\n FsClient,\n LogLevel,\n FsUserContext,\n FeatureFlags,\n} from '@flagsync/node-sdk';\n\nexport { SyncType } from '@flagsync/node-sdk';\n\nexport type { JsonObject } from './types';\n\nexport { createTypedFlag, createClient, createAdapter } from './adapter';\nexport { createIdentify } from './identify';\n","import {\n FeatureFlags,\n FlagReturnType,\n FlagSyncFactory,\n FsClient,\n type FsConfig,\n type FsUserContext,\n NoExplicitReturnType,\n} from '@flagsync/node-sdk';\nimport { Adapter, FlagDeclaration } from 'flags';\nimport { flag } from 'flags/next';\n\n/**\n * Clients are cached on globalThis, keyed by SDK key, so they survive module\n * re-evaluation — Next.js dev HMR and multiple server bundles importing this\n * module would otherwise each construct a fresh client, leaking sync\n * connections (each with default settings if their call site differs).\n * Symbol.for() resolves to the same symbol across bundles in one process.\n */\nconst CLIENT_CACHE_KEY = Symbol.for('@flagsync/nextjs-sdk:clients');\n\nfunction getClientCache(): Map<string, FsClient> {\n const store = globalThis as { [CLIENT_CACHE_KEY]?: Map<string, FsClient> };\n store[CLIENT_CACHE_KEY] ??= new Map();\n return store[CLIENT_CACHE_KEY];\n}\n\n/**\n * Creates a FlagSync client instance that can be used across multiple feature flags.\n * Returns the same instance for repeated calls with the same SDK key, even\n * across HMR reloads — note this means config changes for an existing SDK key\n * only take effect after a server restart.\n */\nexport function createClient(config: FsConfig): FsClient {\n const cache = getClientCache();\n\n const existing = cache.get(config.sdkKey);\n if (existing) {\n return existing;\n }\n\n const instance = FlagSyncFactory({\n ...config,\n metadata: {\n sdkName: '@flagsync/nextjs-sdk',\n sdkVersion: '0.8.6-alpha.1',\n },\n });\n\n const client = instance.client();\n cache.set(config.sdkKey, client);\n return client;\n}\n\n/**\n * Creates an adapter factory that integrates FlagSync with Vercel's feature flag system.\n * This adapter handles the communication between your application and the FlagSync service.\n */\nexport function createAdapter(client: FsClient) {\n let isReady = false;\n\n /**\n * Ensures the FlagSync client is ready before making any flag decisions.\n * This is called internally before each flag evaluation.\n */\n const ensureReady = async () => {\n if (!isReady) {\n await client.waitForReady();\n isReady = true;\n }\n };\n\n function adapter<T = any>(): Adapter<\n FlagReturnType<T, string, FeatureFlags>,\n FsUserContext\n > {\n return {\n async decide({\n key,\n entities,\n defaultValue,\n }: {\n key: string;\n entities?: FsUserContext;\n defaultValue?: FlagReturnType<T, string, FeatureFlags>;\n }): Promise<FlagReturnType<T, string, FeatureFlags>> {\n await ensureReady();\n\n const userContext: FsUserContext = {\n key: 'anonymous',\n ...(entities ?? {}),\n };\n\n return client.flag(userContext, key, defaultValue);\n },\n };\n }\n\n return adapter;\n}\n\n/**\n * Creates an adapter factory that integrates FlagSync with Vercel's feature flag system.\n * This adapter handles the communication between your application and the FlagSync service.\n */\nfunction createTypedAdapter(client: FsClient) {\n let isReady = false;\n\n /**\n * Ensures the FlagSync client is ready before making any flag decisions.\n * This is called internally before each flag evaluation.\n */\n const ensureReady = async () => {\n if (!isReady) {\n await client.waitForReady();\n isReady = true;\n }\n };\n\n /**\n * Creates a generic adapter instance that works with any flag.\n * This function is generic over the expected return type (R) and the key type (K)\n * to correctly type the Adapter's `decide` method.\n *\n * @template R The explicit return type for the flag (e.g., `boolean`, `string`).\n * Defaults to `NoExplicitReturnType` if not provided.\n * @template K The literal string type of the flag key. Defaults to `string`.\n * @returns An `Adapter` instance with its generic `T` correctly set to `FlagReturnType<R, K, FeatureFlags>`.\n */\n function flagSyncAdapter<\n R = NoExplicitReturnType, // The explicit return type generic\n K extends string = string, // The key type generic\n >(): Adapter<FlagReturnType<R, K, FeatureFlags>, FsUserContext> {\n return {\n async decide({\n key,\n entities,\n defaultValue,\n }: {\n key: string; // The Adapter interface mandates 'string' here.\n entities?: FsUserContext;\n defaultValue?: FlagReturnType<R, K, FeatureFlags>;\n }): Promise<FlagReturnType<R, K, FeatureFlags>> {\n await ensureReady();\n\n const userContext: FsUserContext = {\n key: 'anonymous',\n ...(entities ?? {}),\n };\n\n // Call client.flag with the generics R and K.\n // We must cast 'key as K' because the Adapter's 'key' is 'string',\n // but client.flag's 'flagKey' parameter can be more restrictive (e.g., 'keyof FeatureFlags').\n // This means strict key validation for the 'key' parameter is bypassed at this point,\n // but the return type will still be correct.\n return client.flag<R, K>(userContext, key as K, defaultValue);\n },\n };\n }\n\n return flagSyncAdapter;\n}\n\n/**\n * Initializes the FlagSync typed helpers.\n * @param client An FsClient instance from createFlagSyncClient.\n * @returns An object containing the typed `flag` function.\n */\nexport function createTypedFlag(client: FsClient) {\n const adapter = createTypedAdapter(client);\n /**\n * A type-safe wrapper around Vercel's `flag` function that is\n * aware of your FeatureFlags interface.\n */\n function typedFlag<TKey extends keyof FeatureFlags>(\n options: Omit<\n FlagDeclaration<FeatureFlags[TKey], FsUserContext>,\n 'key' | 'adapter' | 'decide'\n > & {\n key: TKey;\n },\n ) {\n const specificAdapter = adapter<FeatureFlags[TKey], TKey>();\n\n const fullFlagDeclaration: FlagDeclaration<\n FeatureFlags[TKey],\n FsUserContext\n > = {\n ...options,\n key: options.key,\n adapter: specificAdapter as unknown as Adapter<\n FeatureFlags[TKey],\n FsUserContext\n >,\n };\n\n return flag(fullFlagDeclaration);\n }\n\n return {\n flag: typedFlag,\n };\n}\n","import { FsUserContext } from '@flagsync/node-sdk';\nimport { Identify } from 'flags';\n\ntype ExtractParams<T> = T extends (params: infer P) => any ? P : never;\n\nexport const createIdentify =\n (\n callback: (\n params: ExtractParams<Identify<FsUserContext>>,\n ) => Promise<FsUserContext> | FsUserContext,\n ): Identify<FsUserContext> =>\n (params) =>\n callback(params);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,IAAAA,mBAAyB;;;ACVzB,sBAQO;AAEP,kBAAqB;AASrB,IAAM,mBAAmB,OAAO,IAAI,8BAA8B;AAElE,SAAS,iBAAwC;AAC/C,QAAM,QAAQ;AACd,QAAM,gBAAgB,MAAM,oBAAI,IAAI;AACpC,SAAO,MAAM,gBAAgB;AAC/B;AAQO,SAAS,aAAa,QAA4B;AACvD,QAAM,QAAQ,eAAe;AAE7B,QAAM,WAAW,MAAM,IAAI,OAAO,MAAM;AACxC,MAAI,UAAU;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,eAAW,iCAAgB;AAAA,IAC/B,GAAG;AAAA,IACH,UAAU;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AAED,QAAM,SAAS,SAAS,OAAO;AAC/B,QAAM,IAAI,OAAO,QAAQ,MAAM;AAC/B,SAAO;AACT;AAMO,SAAS,cAAc,QAAkB;AAC9C,MAAI,UAAU;AAMd,QAAM,cAAc,YAAY;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,aAAa;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,WAAS,UAGP;AACA,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAIqD;AACnD,cAAM,YAAY;AAElB,cAAM,cAA6B;AAAA,UACjC,KAAK;AAAA,UACL,GAAI,YAAY,CAAC;AAAA,QACnB;AAEA,eAAO,OAAO,KAAK,aAAa,KAAK,YAAY;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,mBAAmB,QAAkB;AAC5C,MAAI,UAAU;AAMd,QAAM,cAAc,YAAY;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,aAAa;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAYA,WAAS,kBAGuD;AAC9D,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAIgD;AAC9C,cAAM,YAAY;AAElB,cAAM,cAA6B;AAAA,UACjC,KAAK;AAAA,UACL,GAAI,YAAY,CAAC;AAAA,QACnB;AAOA,eAAO,OAAO,KAAW,aAAa,KAAU,YAAY;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,gBAAgB,QAAkB;AAChD,QAAM,UAAU,mBAAmB,MAAM;AAKzC,WAAS,UACP,SAMA;AACA,UAAM,kBAAkB,QAAkC;AAE1D,UAAM,sBAGF;AAAA,MACF,GAAG;AAAA,MACH,KAAK,QAAQ;AAAA,MACb,SAAS;AAAA,IAIX;AAEA,eAAO,kBAAK,mBAAmB;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;;;ACrMO,IAAM,iBACX,CACE,aAIF,CAAC,WACC,SAAS,MAAM;","names":["import_node_sdk"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/identify.ts"],"sourcesContent":["export type {\n CustomAttributes,\n CustomAttributeValue,\n FsConfig,\n FsClient,\n LogLevel,\n FsUserContext,\n FeatureFlags,\n} from '@flagsync/node-sdk';\n\nexport { SyncType } from '@flagsync/node-sdk';\n\nexport type { JsonObject } from './types';\n\nexport { createTypedFlag, createClient, createAdapter } from './adapter';\nexport { createIdentify } from './identify';\n","import {\n FeatureFlags,\n FlagReturnType,\n FlagSyncFactory,\n FsClient,\n type FsConfig,\n type FsUserContext,\n NoExplicitReturnType,\n} from '@flagsync/node-sdk';\nimport { Adapter, FlagDeclaration } from 'flags';\nimport { flag } from 'flags/next';\n\n/**\n * Clients are cached on globalThis, keyed by SDK key, so they survive module\n * re-evaluation — Next.js dev HMR and multiple server bundles importing this\n * module would otherwise each construct a fresh client, leaking sync\n * connections (each with default settings if their call site differs).\n * Symbol.for() resolves to the same symbol across bundles in one process.\n */\nconst CLIENT_CACHE_KEY = Symbol.for('@flagsync/nextjs-sdk:clients');\n\ninterface CachedClient {\n client: FsClient;\n configFingerprint: string;\n}\n\nfunction getClientCache(): Map<string, CachedClient> {\n const store = globalThis as {\n [CLIENT_CACHE_KEY]?: Map<string, CachedClient>;\n };\n store[CLIENT_CACHE_KEY] ??= new Map();\n return store[CLIENT_CACHE_KEY];\n}\n\n/**\n * Serializable view of the config, used only to detect (and warn about)\n * config changes that cannot apply to an already-cached client. Functions\n * (loggers, etc.) are omitted by JSON.stringify; key order follows the\n * caller's object literal, which is stable for a given call site.\n */\nfunction fingerprintConfig(config: FsConfig): string {\n try {\n return JSON.stringify(config);\n } catch {\n return '';\n }\n}\n\n/**\n * Creates a FlagSync client instance that can be used across multiple feature flags.\n * Returns the same instance for repeated calls with the same SDK key, even\n * across HMR reloads — note this means config changes for an existing SDK key\n * only take effect after a server restart.\n */\nexport function createClient(config: FsConfig): FsClient {\n const cache = getClientCache();\n\n const existing = cache.get(config.sdkKey);\n if (existing) {\n if (\n process.env.NODE_ENV !== 'production' &&\n existing.configFingerprint !== fingerprintConfig(config)\n ) {\n console.warn(\n '***************************************************************',\n );\n console.warn(\n '[flagsync] createClient was called with a changed config, but a ' +\n 'client for this SDK key already exists and will be reused. ' +\n 'Restart the dev server to apply the new config.',\n );\n console.warn(\n '***************************************************************',\n );\n }\n return existing.client;\n }\n\n const instance = FlagSyncFactory({\n ...config,\n metadata: {\n sdkName: '@flagsync/nextjs-sdk',\n sdkVersion: '0.8.6-alpha.3',\n },\n });\n\n const client = instance.client();\n cache.set(config.sdkKey, {\n client,\n configFingerprint: fingerprintConfig(config),\n });\n return client;\n}\n\n/**\n * Creates an adapter factory that integrates FlagSync with Vercel's feature flag system.\n * This adapter handles the communication between your application and the FlagSync service.\n */\nexport function createAdapter(client: FsClient) {\n let isReady = false;\n\n /**\n * Ensures the FlagSync client is ready before making any flag decisions.\n * This is called internally before each flag evaluation.\n */\n const ensureReady = async () => {\n if (!isReady) {\n await client.waitForReady();\n isReady = true;\n }\n };\n\n function adapter<T = any>(): Adapter<\n FlagReturnType<T, string, FeatureFlags>,\n FsUserContext\n > {\n return {\n async decide({\n key,\n entities,\n defaultValue,\n }: {\n key: string;\n entities?: FsUserContext;\n defaultValue?: FlagReturnType<T, string, FeatureFlags>;\n }): Promise<FlagReturnType<T, string, FeatureFlags>> {\n await ensureReady();\n\n const userContext: FsUserContext = {\n key: 'anonymous',\n ...(entities ?? {}),\n };\n\n return client.flag(userContext, key, defaultValue);\n },\n };\n }\n\n return adapter;\n}\n\n/**\n * Creates an adapter factory that integrates FlagSync with Vercel's feature flag system.\n * This adapter handles the communication between your application and the FlagSync service.\n */\nfunction createTypedAdapter(client: FsClient) {\n let isReady = false;\n\n /**\n * Ensures the FlagSync client is ready before making any flag decisions.\n * This is called internally before each flag evaluation.\n */\n const ensureReady = async () => {\n if (!isReady) {\n await client.waitForReady();\n isReady = true;\n }\n };\n\n /**\n * Creates a generic adapter instance that works with any flag.\n * This function is generic over the expected return type (R) and the key type (K)\n * to correctly type the Adapter's `decide` method.\n *\n * @template R The explicit return type for the flag (e.g., `boolean`, `string`).\n * Defaults to `NoExplicitReturnType` if not provided.\n * @template K The literal string type of the flag key. Defaults to `string`.\n * @returns An `Adapter` instance with its generic `T` correctly set to `FlagReturnType<R, K, FeatureFlags>`.\n */\n function flagSyncAdapter<\n R = NoExplicitReturnType, // The explicit return type generic\n K extends string = string, // The key type generic\n >(): Adapter<FlagReturnType<R, K, FeatureFlags>, FsUserContext> {\n return {\n async decide({\n key,\n entities,\n defaultValue,\n }: {\n key: string; // The Adapter interface mandates 'string' here.\n entities?: FsUserContext;\n defaultValue?: FlagReturnType<R, K, FeatureFlags>;\n }): Promise<FlagReturnType<R, K, FeatureFlags>> {\n await ensureReady();\n\n const userContext: FsUserContext = {\n key: 'anonymous',\n ...(entities ?? {}),\n };\n\n // Call client.flag with the generics R and K.\n // We must cast 'key as K' because the Adapter's 'key' is 'string',\n // but client.flag's 'flagKey' parameter can be more restrictive (e.g., 'keyof FeatureFlags').\n // This means strict key validation for the 'key' parameter is bypassed at this point,\n // but the return type will still be correct.\n return client.flag<R, K>(userContext, key as K, defaultValue);\n },\n };\n }\n\n return flagSyncAdapter;\n}\n\n/**\n * Initializes the FlagSync typed helpers.\n * @param client An FsClient instance from createFlagSyncClient.\n * @returns An object containing the typed `flag` function.\n */\nexport function createTypedFlag(client: FsClient) {\n const adapter = createTypedAdapter(client);\n /**\n * A type-safe wrapper around Vercel's `flag` function that is\n * aware of your FeatureFlags interface.\n */\n function typedFlag<TKey extends keyof FeatureFlags>(\n options: Omit<\n FlagDeclaration<FeatureFlags[TKey], FsUserContext>,\n 'key' | 'adapter' | 'decide'\n > & {\n key: TKey;\n },\n ) {\n const specificAdapter = adapter<FeatureFlags[TKey], TKey>();\n\n const fullFlagDeclaration: FlagDeclaration<\n FeatureFlags[TKey],\n FsUserContext\n > = {\n ...options,\n key: options.key,\n adapter: specificAdapter as unknown as Adapter<\n FeatureFlags[TKey],\n FsUserContext\n >,\n };\n\n return flag(fullFlagDeclaration);\n }\n\n return {\n flag: typedFlag,\n };\n}\n","import { FsUserContext } from '@flagsync/node-sdk';\nimport { Identify } from 'flags';\n\ntype ExtractParams<T> = T extends (params: infer P) => any ? P : never;\n\nexport const createIdentify =\n (\n callback: (\n params: ExtractParams<Identify<FsUserContext>>,\n ) => Promise<FsUserContext> | FsUserContext,\n ): Identify<FsUserContext> =>\n (params) =>\n callback(params);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,IAAAA,mBAAyB;;;ACVzB,sBAQO;AAEP,kBAAqB;AASrB,IAAM,mBAAmB,OAAO,IAAI,8BAA8B;AAOlE,SAAS,iBAA4C;AACnD,QAAM,QAAQ;AAGd,QAAM,gBAAgB,MAAM,oBAAI,IAAI;AACpC,SAAO,MAAM,gBAAgB;AAC/B;AAQA,SAAS,kBAAkB,QAA0B;AACnD,MAAI;AACF,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,aAAa,QAA4B;AACvD,QAAM,QAAQ,eAAe;AAE7B,QAAM,WAAW,MAAM,IAAI,OAAO,MAAM;AACxC,MAAI,UAAU;AACZ,QACE,QAAQ,IAAI,aAAa,gBACzB,SAAS,sBAAsB,kBAAkB,MAAM,GACvD;AACA,cAAQ;AAAA,QACN;AAAA,MACF;AACA,cAAQ;AAAA,QACN;AAAA,MAGF;AACA,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AAEA,QAAM,eAAW,iCAAgB;AAAA,IAC/B,GAAG;AAAA,IACH,UAAU;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AAED,QAAM,SAAS,SAAS,OAAO;AAC/B,QAAM,IAAI,OAAO,QAAQ;AAAA,IACvB;AAAA,IACA,mBAAmB,kBAAkB,MAAM;AAAA,EAC7C,CAAC;AACD,SAAO;AACT;AAMO,SAAS,cAAc,QAAkB;AAC9C,MAAI,UAAU;AAMd,QAAM,cAAc,YAAY;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,aAAa;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,WAAS,UAGP;AACA,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAIqD;AACnD,cAAM,YAAY;AAElB,cAAM,cAA6B;AAAA,UACjC,KAAK;AAAA,UACL,GAAI,YAAY,CAAC;AAAA,QACnB;AAEA,eAAO,OAAO,KAAK,aAAa,KAAK,YAAY;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,mBAAmB,QAAkB;AAC5C,MAAI,UAAU;AAMd,QAAM,cAAc,YAAY;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,aAAa;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAYA,WAAS,kBAGuD;AAC9D,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAIgD;AAC9C,cAAM,YAAY;AAElB,cAAM,cAA6B;AAAA,UACjC,KAAK;AAAA,UACL,GAAI,YAAY,CAAC;AAAA,QACnB;AAOA,eAAO,OAAO,KAAW,aAAa,KAAU,YAAY;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,gBAAgB,QAAkB;AAChD,QAAM,UAAU,mBAAmB,MAAM;AAKzC,WAAS,UACP,SAMA;AACA,UAAM,kBAAkB,QAAkC;AAE1D,UAAM,sBAGF;AAAA,MACF,GAAG;AAAA,MACH,KAAK,QAAQ;AAAA,MACb,SAAS;AAAA,IAIX;AAEA,eAAO,kBAAK,mBAAmB;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;;;AC7OO,IAAM,iBACX,CACE,aAIF,CAAC,WACC,SAAS,MAAM;","names":["import_node_sdk"]}
|
package/dist/index.js
CHANGED
|
@@ -12,21 +12,42 @@ function getClientCache() {
|
|
|
12
12
|
store[CLIENT_CACHE_KEY] ??= /* @__PURE__ */ new Map();
|
|
13
13
|
return store[CLIENT_CACHE_KEY];
|
|
14
14
|
}
|
|
15
|
+
function fingerprintConfig(config) {
|
|
16
|
+
try {
|
|
17
|
+
return JSON.stringify(config);
|
|
18
|
+
} catch {
|
|
19
|
+
return "";
|
|
20
|
+
}
|
|
21
|
+
}
|
|
15
22
|
function createClient(config) {
|
|
16
23
|
const cache = getClientCache();
|
|
17
24
|
const existing = cache.get(config.sdkKey);
|
|
18
25
|
if (existing) {
|
|
19
|
-
|
|
26
|
+
if (process.env.NODE_ENV !== "production" && existing.configFingerprint !== fingerprintConfig(config)) {
|
|
27
|
+
console.warn(
|
|
28
|
+
"***************************************************************"
|
|
29
|
+
);
|
|
30
|
+
console.warn(
|
|
31
|
+
"[flagsync] createClient was called with a changed config, but a client for this SDK key already exists and will be reused. Restart the dev server to apply the new config."
|
|
32
|
+
);
|
|
33
|
+
console.warn(
|
|
34
|
+
"***************************************************************"
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return existing.client;
|
|
20
38
|
}
|
|
21
39
|
const instance = FlagSyncFactory({
|
|
22
40
|
...config,
|
|
23
41
|
metadata: {
|
|
24
42
|
sdkName: "@flagsync/nextjs-sdk",
|
|
25
|
-
sdkVersion: "0.8.6-alpha.
|
|
43
|
+
sdkVersion: "0.8.6-alpha.3"
|
|
26
44
|
}
|
|
27
45
|
});
|
|
28
46
|
const client = instance.client();
|
|
29
|
-
cache.set(config.sdkKey,
|
|
47
|
+
cache.set(config.sdkKey, {
|
|
48
|
+
client,
|
|
49
|
+
configFingerprint: fingerprintConfig(config)
|
|
50
|
+
});
|
|
30
51
|
return client;
|
|
31
52
|
}
|
|
32
53
|
function createAdapter(client) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/identify.ts"],"sourcesContent":["export type {\n CustomAttributes,\n CustomAttributeValue,\n FsConfig,\n FsClient,\n LogLevel,\n FsUserContext,\n FeatureFlags,\n} from '@flagsync/node-sdk';\n\nexport { SyncType } from '@flagsync/node-sdk';\n\nexport type { JsonObject } from './types';\n\nexport { createTypedFlag, createClient, createAdapter } from './adapter';\nexport { createIdentify } from './identify';\n","import {\n FeatureFlags,\n FlagReturnType,\n FlagSyncFactory,\n FsClient,\n type FsConfig,\n type FsUserContext,\n NoExplicitReturnType,\n} from '@flagsync/node-sdk';\nimport { Adapter, FlagDeclaration } from 'flags';\nimport { flag } from 'flags/next';\n\n/**\n * Clients are cached on globalThis, keyed by SDK key, so they survive module\n * re-evaluation — Next.js dev HMR and multiple server bundles importing this\n * module would otherwise each construct a fresh client, leaking sync\n * connections (each with default settings if their call site differs).\n * Symbol.for() resolves to the same symbol across bundles in one process.\n */\nconst CLIENT_CACHE_KEY = Symbol.for('@flagsync/nextjs-sdk:clients');\n\nfunction getClientCache(): Map<string, FsClient> {\n const store = globalThis as { [CLIENT_CACHE_KEY]?: Map<string, FsClient> };\n store[CLIENT_CACHE_KEY] ??= new Map();\n return store[CLIENT_CACHE_KEY];\n}\n\n/**\n * Creates a FlagSync client instance that can be used across multiple feature flags.\n * Returns the same instance for repeated calls with the same SDK key, even\n * across HMR reloads — note this means config changes for an existing SDK key\n * only take effect after a server restart.\n */\nexport function createClient(config: FsConfig): FsClient {\n const cache = getClientCache();\n\n const existing = cache.get(config.sdkKey);\n if (existing) {\n return existing;\n }\n\n const instance = FlagSyncFactory({\n ...config,\n metadata: {\n sdkName: '@flagsync/nextjs-sdk',\n sdkVersion: '0.8.6-alpha.1',\n },\n });\n\n const client = instance.client();\n cache.set(config.sdkKey, client);\n return client;\n}\n\n/**\n * Creates an adapter factory that integrates FlagSync with Vercel's feature flag system.\n * This adapter handles the communication between your application and the FlagSync service.\n */\nexport function createAdapter(client: FsClient) {\n let isReady = false;\n\n /**\n * Ensures the FlagSync client is ready before making any flag decisions.\n * This is called internally before each flag evaluation.\n */\n const ensureReady = async () => {\n if (!isReady) {\n await client.waitForReady();\n isReady = true;\n }\n };\n\n function adapter<T = any>(): Adapter<\n FlagReturnType<T, string, FeatureFlags>,\n FsUserContext\n > {\n return {\n async decide({\n key,\n entities,\n defaultValue,\n }: {\n key: string;\n entities?: FsUserContext;\n defaultValue?: FlagReturnType<T, string, FeatureFlags>;\n }): Promise<FlagReturnType<T, string, FeatureFlags>> {\n await ensureReady();\n\n const userContext: FsUserContext = {\n key: 'anonymous',\n ...(entities ?? {}),\n };\n\n return client.flag(userContext, key, defaultValue);\n },\n };\n }\n\n return adapter;\n}\n\n/**\n * Creates an adapter factory that integrates FlagSync with Vercel's feature flag system.\n * This adapter handles the communication between your application and the FlagSync service.\n */\nfunction createTypedAdapter(client: FsClient) {\n let isReady = false;\n\n /**\n * Ensures the FlagSync client is ready before making any flag decisions.\n * This is called internally before each flag evaluation.\n */\n const ensureReady = async () => {\n if (!isReady) {\n await client.waitForReady();\n isReady = true;\n }\n };\n\n /**\n * Creates a generic adapter instance that works with any flag.\n * This function is generic over the expected return type (R) and the key type (K)\n * to correctly type the Adapter's `decide` method.\n *\n * @template R The explicit return type for the flag (e.g., `boolean`, `string`).\n * Defaults to `NoExplicitReturnType` if not provided.\n * @template K The literal string type of the flag key. Defaults to `string`.\n * @returns An `Adapter` instance with its generic `T` correctly set to `FlagReturnType<R, K, FeatureFlags>`.\n */\n function flagSyncAdapter<\n R = NoExplicitReturnType, // The explicit return type generic\n K extends string = string, // The key type generic\n >(): Adapter<FlagReturnType<R, K, FeatureFlags>, FsUserContext> {\n return {\n async decide({\n key,\n entities,\n defaultValue,\n }: {\n key: string; // The Adapter interface mandates 'string' here.\n entities?: FsUserContext;\n defaultValue?: FlagReturnType<R, K, FeatureFlags>;\n }): Promise<FlagReturnType<R, K, FeatureFlags>> {\n await ensureReady();\n\n const userContext: FsUserContext = {\n key: 'anonymous',\n ...(entities ?? {}),\n };\n\n // Call client.flag with the generics R and K.\n // We must cast 'key as K' because the Adapter's 'key' is 'string',\n // but client.flag's 'flagKey' parameter can be more restrictive (e.g., 'keyof FeatureFlags').\n // This means strict key validation for the 'key' parameter is bypassed at this point,\n // but the return type will still be correct.\n return client.flag<R, K>(userContext, key as K, defaultValue);\n },\n };\n }\n\n return flagSyncAdapter;\n}\n\n/**\n * Initializes the FlagSync typed helpers.\n * @param client An FsClient instance from createFlagSyncClient.\n * @returns An object containing the typed `flag` function.\n */\nexport function createTypedFlag(client: FsClient) {\n const adapter = createTypedAdapter(client);\n /**\n * A type-safe wrapper around Vercel's `flag` function that is\n * aware of your FeatureFlags interface.\n */\n function typedFlag<TKey extends keyof FeatureFlags>(\n options: Omit<\n FlagDeclaration<FeatureFlags[TKey], FsUserContext>,\n 'key' | 'adapter' | 'decide'\n > & {\n key: TKey;\n },\n ) {\n const specificAdapter = adapter<FeatureFlags[TKey], TKey>();\n\n const fullFlagDeclaration: FlagDeclaration<\n FeatureFlags[TKey],\n FsUserContext\n > = {\n ...options,\n key: options.key,\n adapter: specificAdapter as unknown as Adapter<\n FeatureFlags[TKey],\n FsUserContext\n >,\n };\n\n return flag(fullFlagDeclaration);\n }\n\n return {\n flag: typedFlag,\n };\n}\n","import { FsUserContext } from '@flagsync/node-sdk';\nimport { Identify } from 'flags';\n\ntype ExtractParams<T> = T extends (params: infer P) => any ? P : never;\n\nexport const createIdentify =\n (\n callback: (\n params: ExtractParams<Identify<FsUserContext>>,\n ) => Promise<FsUserContext> | FsUserContext,\n ): Identify<FsUserContext> =>\n (params) =>\n callback(params);\n"],"mappings":";AAUA,SAAS,gBAAgB;;;ACVzB;AAAA,EAGE;AAAA,OAKK;AAEP,SAAS,YAAY;AASrB,IAAM,mBAAmB,OAAO,IAAI,8BAA8B;AAElE,SAAS,iBAAwC;AAC/C,QAAM,QAAQ;AACd,QAAM,gBAAgB,MAAM,oBAAI,IAAI;AACpC,SAAO,MAAM,gBAAgB;AAC/B;AAQO,SAAS,aAAa,QAA4B;AACvD,QAAM,QAAQ,eAAe;AAE7B,QAAM,WAAW,MAAM,IAAI,OAAO,MAAM;AACxC,MAAI,UAAU;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,gBAAgB;AAAA,IAC/B,GAAG;AAAA,IACH,UAAU;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AAED,QAAM,SAAS,SAAS,OAAO;AAC/B,QAAM,IAAI,OAAO,QAAQ,MAAM;AAC/B,SAAO;AACT;AAMO,SAAS,cAAc,QAAkB;AAC9C,MAAI,UAAU;AAMd,QAAM,cAAc,YAAY;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,aAAa;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,WAAS,UAGP;AACA,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAIqD;AACnD,cAAM,YAAY;AAElB,cAAM,cAA6B;AAAA,UACjC,KAAK;AAAA,UACL,GAAI,YAAY,CAAC;AAAA,QACnB;AAEA,eAAO,OAAO,KAAK,aAAa,KAAK,YAAY;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,mBAAmB,QAAkB;AAC5C,MAAI,UAAU;AAMd,QAAM,cAAc,YAAY;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,aAAa;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAYA,WAAS,kBAGuD;AAC9D,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAIgD;AAC9C,cAAM,YAAY;AAElB,cAAM,cAA6B;AAAA,UACjC,KAAK;AAAA,UACL,GAAI,YAAY,CAAC;AAAA,QACnB;AAOA,eAAO,OAAO,KAAW,aAAa,KAAU,YAAY;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,gBAAgB,QAAkB;AAChD,QAAM,UAAU,mBAAmB,MAAM;AAKzC,WAAS,UACP,SAMA;AACA,UAAM,kBAAkB,QAAkC;AAE1D,UAAM,sBAGF;AAAA,MACF,GAAG;AAAA,MACH,KAAK,QAAQ;AAAA,MACb,SAAS;AAAA,IAIX;AAEA,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;;;ACrMO,IAAM,iBACX,CACE,aAIF,CAAC,WACC,SAAS,MAAM;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/adapter.ts","../src/identify.ts"],"sourcesContent":["export type {\n CustomAttributes,\n CustomAttributeValue,\n FsConfig,\n FsClient,\n LogLevel,\n FsUserContext,\n FeatureFlags,\n} from '@flagsync/node-sdk';\n\nexport { SyncType } from '@flagsync/node-sdk';\n\nexport type { JsonObject } from './types';\n\nexport { createTypedFlag, createClient, createAdapter } from './adapter';\nexport { createIdentify } from './identify';\n","import {\n FeatureFlags,\n FlagReturnType,\n FlagSyncFactory,\n FsClient,\n type FsConfig,\n type FsUserContext,\n NoExplicitReturnType,\n} from '@flagsync/node-sdk';\nimport { Adapter, FlagDeclaration } from 'flags';\nimport { flag } from 'flags/next';\n\n/**\n * Clients are cached on globalThis, keyed by SDK key, so they survive module\n * re-evaluation — Next.js dev HMR and multiple server bundles importing this\n * module would otherwise each construct a fresh client, leaking sync\n * connections (each with default settings if their call site differs).\n * Symbol.for() resolves to the same symbol across bundles in one process.\n */\nconst CLIENT_CACHE_KEY = Symbol.for('@flagsync/nextjs-sdk:clients');\n\ninterface CachedClient {\n client: FsClient;\n configFingerprint: string;\n}\n\nfunction getClientCache(): Map<string, CachedClient> {\n const store = globalThis as {\n [CLIENT_CACHE_KEY]?: Map<string, CachedClient>;\n };\n store[CLIENT_CACHE_KEY] ??= new Map();\n return store[CLIENT_CACHE_KEY];\n}\n\n/**\n * Serializable view of the config, used only to detect (and warn about)\n * config changes that cannot apply to an already-cached client. Functions\n * (loggers, etc.) are omitted by JSON.stringify; key order follows the\n * caller's object literal, which is stable for a given call site.\n */\nfunction fingerprintConfig(config: FsConfig): string {\n try {\n return JSON.stringify(config);\n } catch {\n return '';\n }\n}\n\n/**\n * Creates a FlagSync client instance that can be used across multiple feature flags.\n * Returns the same instance for repeated calls with the same SDK key, even\n * across HMR reloads — note this means config changes for an existing SDK key\n * only take effect after a server restart.\n */\nexport function createClient(config: FsConfig): FsClient {\n const cache = getClientCache();\n\n const existing = cache.get(config.sdkKey);\n if (existing) {\n if (\n process.env.NODE_ENV !== 'production' &&\n existing.configFingerprint !== fingerprintConfig(config)\n ) {\n console.warn(\n '***************************************************************',\n );\n console.warn(\n '[flagsync] createClient was called with a changed config, but a ' +\n 'client for this SDK key already exists and will be reused. ' +\n 'Restart the dev server to apply the new config.',\n );\n console.warn(\n '***************************************************************',\n );\n }\n return existing.client;\n }\n\n const instance = FlagSyncFactory({\n ...config,\n metadata: {\n sdkName: '@flagsync/nextjs-sdk',\n sdkVersion: '0.8.6-alpha.3',\n },\n });\n\n const client = instance.client();\n cache.set(config.sdkKey, {\n client,\n configFingerprint: fingerprintConfig(config),\n });\n return client;\n}\n\n/**\n * Creates an adapter factory that integrates FlagSync with Vercel's feature flag system.\n * This adapter handles the communication between your application and the FlagSync service.\n */\nexport function createAdapter(client: FsClient) {\n let isReady = false;\n\n /**\n * Ensures the FlagSync client is ready before making any flag decisions.\n * This is called internally before each flag evaluation.\n */\n const ensureReady = async () => {\n if (!isReady) {\n await client.waitForReady();\n isReady = true;\n }\n };\n\n function adapter<T = any>(): Adapter<\n FlagReturnType<T, string, FeatureFlags>,\n FsUserContext\n > {\n return {\n async decide({\n key,\n entities,\n defaultValue,\n }: {\n key: string;\n entities?: FsUserContext;\n defaultValue?: FlagReturnType<T, string, FeatureFlags>;\n }): Promise<FlagReturnType<T, string, FeatureFlags>> {\n await ensureReady();\n\n const userContext: FsUserContext = {\n key: 'anonymous',\n ...(entities ?? {}),\n };\n\n return client.flag(userContext, key, defaultValue);\n },\n };\n }\n\n return adapter;\n}\n\n/**\n * Creates an adapter factory that integrates FlagSync with Vercel's feature flag system.\n * This adapter handles the communication between your application and the FlagSync service.\n */\nfunction createTypedAdapter(client: FsClient) {\n let isReady = false;\n\n /**\n * Ensures the FlagSync client is ready before making any flag decisions.\n * This is called internally before each flag evaluation.\n */\n const ensureReady = async () => {\n if (!isReady) {\n await client.waitForReady();\n isReady = true;\n }\n };\n\n /**\n * Creates a generic adapter instance that works with any flag.\n * This function is generic over the expected return type (R) and the key type (K)\n * to correctly type the Adapter's `decide` method.\n *\n * @template R The explicit return type for the flag (e.g., `boolean`, `string`).\n * Defaults to `NoExplicitReturnType` if not provided.\n * @template K The literal string type of the flag key. Defaults to `string`.\n * @returns An `Adapter` instance with its generic `T` correctly set to `FlagReturnType<R, K, FeatureFlags>`.\n */\n function flagSyncAdapter<\n R = NoExplicitReturnType, // The explicit return type generic\n K extends string = string, // The key type generic\n >(): Adapter<FlagReturnType<R, K, FeatureFlags>, FsUserContext> {\n return {\n async decide({\n key,\n entities,\n defaultValue,\n }: {\n key: string; // The Adapter interface mandates 'string' here.\n entities?: FsUserContext;\n defaultValue?: FlagReturnType<R, K, FeatureFlags>;\n }): Promise<FlagReturnType<R, K, FeatureFlags>> {\n await ensureReady();\n\n const userContext: FsUserContext = {\n key: 'anonymous',\n ...(entities ?? {}),\n };\n\n // Call client.flag with the generics R and K.\n // We must cast 'key as K' because the Adapter's 'key' is 'string',\n // but client.flag's 'flagKey' parameter can be more restrictive (e.g., 'keyof FeatureFlags').\n // This means strict key validation for the 'key' parameter is bypassed at this point,\n // but the return type will still be correct.\n return client.flag<R, K>(userContext, key as K, defaultValue);\n },\n };\n }\n\n return flagSyncAdapter;\n}\n\n/**\n * Initializes the FlagSync typed helpers.\n * @param client An FsClient instance from createFlagSyncClient.\n * @returns An object containing the typed `flag` function.\n */\nexport function createTypedFlag(client: FsClient) {\n const adapter = createTypedAdapter(client);\n /**\n * A type-safe wrapper around Vercel's `flag` function that is\n * aware of your FeatureFlags interface.\n */\n function typedFlag<TKey extends keyof FeatureFlags>(\n options: Omit<\n FlagDeclaration<FeatureFlags[TKey], FsUserContext>,\n 'key' | 'adapter' | 'decide'\n > & {\n key: TKey;\n },\n ) {\n const specificAdapter = adapter<FeatureFlags[TKey], TKey>();\n\n const fullFlagDeclaration: FlagDeclaration<\n FeatureFlags[TKey],\n FsUserContext\n > = {\n ...options,\n key: options.key,\n adapter: specificAdapter as unknown as Adapter<\n FeatureFlags[TKey],\n FsUserContext\n >,\n };\n\n return flag(fullFlagDeclaration);\n }\n\n return {\n flag: typedFlag,\n };\n}\n","import { FsUserContext } from '@flagsync/node-sdk';\nimport { Identify } from 'flags';\n\ntype ExtractParams<T> = T extends (params: infer P) => any ? P : never;\n\nexport const createIdentify =\n (\n callback: (\n params: ExtractParams<Identify<FsUserContext>>,\n ) => Promise<FsUserContext> | FsUserContext,\n ): Identify<FsUserContext> =>\n (params) =>\n callback(params);\n"],"mappings":";AAUA,SAAS,gBAAgB;;;ACVzB;AAAA,EAGE;AAAA,OAKK;AAEP,SAAS,YAAY;AASrB,IAAM,mBAAmB,OAAO,IAAI,8BAA8B;AAOlE,SAAS,iBAA4C;AACnD,QAAM,QAAQ;AAGd,QAAM,gBAAgB,MAAM,oBAAI,IAAI;AACpC,SAAO,MAAM,gBAAgB;AAC/B;AAQA,SAAS,kBAAkB,QAA0B;AACnD,MAAI;AACF,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,aAAa,QAA4B;AACvD,QAAM,QAAQ,eAAe;AAE7B,QAAM,WAAW,MAAM,IAAI,OAAO,MAAM;AACxC,MAAI,UAAU;AACZ,QACE,QAAQ,IAAI,aAAa,gBACzB,SAAS,sBAAsB,kBAAkB,MAAM,GACvD;AACA,cAAQ;AAAA,QACN;AAAA,MACF;AACA,cAAQ;AAAA,QACN;AAAA,MAGF;AACA,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AAEA,QAAM,WAAW,gBAAgB;AAAA,IAC/B,GAAG;AAAA,IACH,UAAU;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AAED,QAAM,SAAS,SAAS,OAAO;AAC/B,QAAM,IAAI,OAAO,QAAQ;AAAA,IACvB;AAAA,IACA,mBAAmB,kBAAkB,MAAM;AAAA,EAC7C,CAAC;AACD,SAAO;AACT;AAMO,SAAS,cAAc,QAAkB;AAC9C,MAAI,UAAU;AAMd,QAAM,cAAc,YAAY;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,aAAa;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,WAAS,UAGP;AACA,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAIqD;AACnD,cAAM,YAAY;AAElB,cAAM,cAA6B;AAAA,UACjC,KAAK;AAAA,UACL,GAAI,YAAY,CAAC;AAAA,QACnB;AAEA,eAAO,OAAO,KAAK,aAAa,KAAK,YAAY;AAAA,MACnD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,mBAAmB,QAAkB;AAC5C,MAAI,UAAU;AAMd,QAAM,cAAc,YAAY;AAC9B,QAAI,CAAC,SAAS;AACZ,YAAM,OAAO,aAAa;AAC1B,gBAAU;AAAA,IACZ;AAAA,EACF;AAYA,WAAS,kBAGuD;AAC9D,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF,GAIgD;AAC9C,cAAM,YAAY;AAElB,cAAM,cAA6B;AAAA,UACjC,KAAK;AAAA,UACL,GAAI,YAAY,CAAC;AAAA,QACnB;AAOA,eAAO,OAAO,KAAW,aAAa,KAAU,YAAY;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,gBAAgB,QAAkB;AAChD,QAAM,UAAU,mBAAmB,MAAM;AAKzC,WAAS,UACP,SAMA;AACA,UAAM,kBAAkB,QAAkC;AAE1D,UAAM,sBAGF;AAAA,MACF,GAAG;AAAA,MACH,KAAK,QAAQ;AAAA,MACb,SAAS;AAAA,IAIX;AAEA,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,EACR;AACF;;;AC7OO,IAAM,iBACX,CACE,aAIF,CAAC,WACC,SAAS,MAAM;","names":[]}
|