{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AACA;AAAA,EACE;AAAA,OAIK;AAaP,IAAI;AAEJ,SAAS,UAAU,MAAsB;AACvC,QAAM,QAAQ,QAAQ,IAAI,IAAI;AAC9B,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,8BAA8B,IAAI,uBAAuB;AAAA,EAC3E;AACA,SAAO;AACT;AAEO,SAAS,oBACd,eACiB;AACjB,MAAI;AAEJ,iBAAe,aAAa;AAC1B,QAAI,CAAC,cAAc;AACjB,UAAI;AACF,uBAAe,IAAI,aAAa,aAAa;AAAA,MAC/C,SAAS,KAAK;AAEZ,gBAAQ,MAAM,kDAAkD,GAAG;AACnE,cAAM;AAAA,MACR;AAAA,IACF;AAGA,WAAO,aAAa,WAAW;AAAA,EACjC;AAEA,WAAS,iBACP,SAC2B;AAC3B,WAAO;AAAA,MACL,MAAM,OAAO,EAAE,KAAK,SAAS,GAAqB;AAChD,cAAM,WAAW;AAEjB,eAAO,aAAa,WAAW,EAAE,GAAG,SAAS,GAAG,SAAS,GAAG,GAAG,EAC5D;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAc,YAAY;AACxB,YAAM,WAAW;AACjB,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAEA,SAAS,4BAA4B;AACnC,MAAI,CAAC,sBAAsB;AACzB,UAAM,YAAY,UAAU,mBAAmB;AAE/C,2BAAuB,oBAAoB,EAAE,UAAU,CAAC;AAAA,EAC1D;AAEA,SAAO;AACT;AAuBO,IAAM,gBAAiC;AAAA,EAC5C,kBAAkB,IAAI,SACpB,0BAA0B,EAAE,iBAAiB,GAAG,IAAI;AAAA,EACtD,cAAc,YAAY;AACxB,WAAO,0BAA0B,EAAE,aAAa;AAAA,EAClD;AACF;AAuBA,eAAsB,gBAAgB;AAAA,EACpC;AACF,IAKI,CAAC,GAA0B;AAC7B,MAAI,CAAC,cAAc;AACjB,mBAAe,MAAM,0BAA0B,EAAE,aAAa;AAAA,EAChE;AAEA,QAAM,WAAW,MAAM,aAAa,sBAAsB;AAE1D,SAAO;AAAA,IACL,aAAa,SAAS,OAA4B,CAAC,KAAK,SAAS;AAC/D,UAAI,KAAK,GAAG,IAAI;AAAA,QACd,SAAS;AAAA,UACP,EAAE,OAAO,YAAY,OAAO,MAAM;AAAA,UAClC,EAAE,OAAO,WAAW,OAAO,KAAK;AAAA,QAClC;AAAA,QACA,aAAa,KAAK,eAAe;AAAA,MACnC;AACA,aAAO;AAAA,IACT,GAAG,CAAC,CAAC;AAAA,IACL,OAAO,CAAC;AAAA,EACV;AACF","sourcesContent":["import type { Adapter, FlagDefinitionsType } from 'flags';\nimport {\n  BucketClient,\n  ClientOptions,\n  Context,\n  ContextWithTracking,\n} from '@bucketco/node-sdk';\nimport { ProviderData } from 'flags';\n\nexport type { Context };\n\ntype AdapterOptions = Pick<ContextWithTracking, 'enableTracking' | 'meta'>;\n\ntype AdapterResponse = {\n  featureIsEnabled: (options?: AdapterOptions) => Adapter<boolean, Context>;\n  /** The Bucket client instance used by the adapter. */\n  bucketClient: () => Promise<BucketClient>;\n};\n\nlet defaultBucketAdapter: ReturnType<typeof createBucketAdapter> | undefined;\n\nfunction assertEnv(name: string): string {\n  const value = process.env[name];\n  if (!value) {\n    throw new Error(`@flags-sdk/bucket: Missing ${name} environment variable`);\n  }\n  return value;\n}\n\nexport function createBucketAdapter(\n  clientOptions: ClientOptions,\n): AdapterResponse {\n  let bucketClient: BucketClient;\n\n  async function initialize() {\n    if (!bucketClient) {\n      try {\n        bucketClient = new BucketClient(clientOptions);\n      } catch (err) {\n        // explicitly log out the error, otherwise it's swallowed\n        console.error('@flags-sdk/bucket: Error creating bucketClient', err);\n        throw err;\n      }\n    }\n\n    // this can be called multiple times. Same promise is returned.\n    return bucketClient.initialize();\n  }\n\n  function featureIsEnabled(\n    options?: AdapterOptions,\n  ): Adapter<boolean, Context> {\n    return {\n      async decide({ key, entities }): Promise<boolean> {\n        await initialize();\n\n        return bucketClient.getFeature({ ...options, ...entities }, key)\n          .isEnabled;\n      },\n    };\n  }\n\n  return {\n    featureIsEnabled,\n    bucketClient: async () => {\n      await initialize();\n      return bucketClient;\n    },\n  };\n}\n\nfunction getOrCreateDefaultAdapter() {\n  if (!defaultBucketAdapter) {\n    const secretKey = assertEnv('BUCKET_SECRET_KEY');\n\n    defaultBucketAdapter = createBucketAdapter({ secretKey });\n  }\n\n  return defaultBucketAdapter;\n}\n\n/**\n * The default Bucket adapter.\n *\n * This is a convenience object that pre-initializes the Bucket SDK and provides\n * the adapter function for usage with the Flags SDK.\n *\n * This is the recommended way to use the Bucket adapter.\n *\n * ```ts\n * // flags.ts\n * import { flag } from 'flags/next';\n * import { bucketAdapter, type Context } from '@flags-sdk/bucket';\n *\n * const flag = flag<boolean, Context>({\n *   key: 'my-flag',\n *   defaultValue: false,\n *   identify: () => ({ key: \"user-123\" }),\n *   adapter: bucketAdapter.featureIsEnabled(),\n * });\n * ```\n */\nexport const bucketAdapter: AdapterResponse = {\n  featureIsEnabled: (...args) =>\n    getOrCreateDefaultAdapter().featureIsEnabled(...args),\n  bucketClient: async () => {\n    return getOrCreateDefaultAdapter().bucketClient();\n  },\n};\n\n/**\n * Get the provider data for the Bucket adapter.\n *\n * This function is used the the [Flags API endpoint](https://vercel.com/docs/workflow-collaboration/feature-flags/implement-flags-in-toolbar#creating-the-flags-api-endpoint) to load and emit your Bucket data.\n *\n * ```ts\n * // .well-known/vercel/flags/route.ts\n * import { NextResponse, type NextRequest } from 'next/server';\n * import { verifyAccess, type ApiData } from 'flags';\n * import { bucketAdapter, getProviderData } from '@flags-sdk/bucket';\n *\n * export async function GET(request: NextRequest) {\n *   const access = await verifyAccess(request.headers.get('Authorization'));\n *   if (!access) return NextResponse.json(null, { status: 401 });\n *\n *   return NextResponse.json<ApiData>(\n *     await getProviderData({ bucketClient: await bucketAdapter.bucketClient() }),\n *   );\n * }\n * ```\n */\nexport async function getProviderData({\n  bucketClient,\n}: {\n  /**\n   * The BucketClient instance.\n   */\n  bucketClient?: BucketClient;\n} = {}): Promise<ProviderData> {\n  if (!bucketClient) {\n    bucketClient = await getOrCreateDefaultAdapter().bucketClient();\n  }\n\n  const features = await bucketClient.getFeatureDefinitions();\n\n  return {\n    definitions: features.reduce<FlagDefinitionsType>((acc, item) => {\n      acc[item.key] = {\n        options: [\n          { label: 'Disabled', value: false },\n          { label: 'Enabled', value: true },\n        ],\n        description: item.description ?? undefined,\n      };\n      return acc;\n    }, {}),\n    hints: [],\n  };\n}\n"]}