featuredrop 1.3.0 → 2.1.0

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.
Files changed (76) hide show
  1. package/README.md +287 -760
  2. package/dist/adapters.cjs +1757 -0
  3. package/dist/adapters.cjs.map +1 -0
  4. package/dist/adapters.d.cts +744 -0
  5. package/dist/adapters.d.ts +744 -0
  6. package/dist/adapters.js +1745 -0
  7. package/dist/adapters.js.map +1 -0
  8. package/dist/admin.cjs +148 -32
  9. package/dist/admin.cjs.map +1 -1
  10. package/dist/admin.d.cts +14 -3
  11. package/dist/admin.d.ts +14 -3
  12. package/dist/admin.js +148 -32
  13. package/dist/admin.js.map +1 -1
  14. package/dist/bridges.cjs +134 -15
  15. package/dist/bridges.cjs.map +1 -1
  16. package/dist/bridges.d.cts +12 -5
  17. package/dist/bridges.d.ts +12 -5
  18. package/dist/bridges.js +114 -15
  19. package/dist/bridges.js.map +1 -1
  20. package/dist/ci.cjs +34 -0
  21. package/dist/ci.cjs.map +1 -1
  22. package/dist/ci.d.cts +5 -1
  23. package/dist/ci.d.ts +5 -1
  24. package/dist/ci.js +34 -1
  25. package/dist/ci.js.map +1 -1
  26. package/dist/cms.cjs +835 -0
  27. package/dist/cms.cjs.map +1 -0
  28. package/dist/cms.d.cts +236 -0
  29. package/dist/cms.d.ts +236 -0
  30. package/dist/cms.js +829 -0
  31. package/dist/cms.js.map +1 -0
  32. package/dist/featuredrop.cjs +23 -2
  33. package/dist/featuredrop.cjs.map +1 -1
  34. package/dist/flags.cjs +27 -7
  35. package/dist/flags.cjs.map +1 -1
  36. package/dist/flags.d.cts +14 -0
  37. package/dist/flags.d.ts +14 -0
  38. package/dist/flags.js +27 -7
  39. package/dist/flags.js.map +1 -1
  40. package/dist/index.cjs +52 -4460
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +1 -1340
  43. package/dist/index.d.ts +1 -1340
  44. package/dist/index.js +53 -4387
  45. package/dist/index.js.map +1 -1
  46. package/dist/markdown.cjs +257 -0
  47. package/dist/markdown.cjs.map +1 -0
  48. package/dist/markdown.d.cts +9 -0
  49. package/dist/markdown.d.ts +9 -0
  50. package/dist/markdown.js +234 -0
  51. package/dist/markdown.js.map +1 -0
  52. package/dist/preact.cjs +37 -12
  53. package/dist/preact.cjs.map +1 -1
  54. package/dist/preact.js +17 -12
  55. package/dist/preact.js.map +1 -1
  56. package/dist/react.cjs +37 -12
  57. package/dist/react.cjs.map +1 -1
  58. package/dist/react.js +17 -12
  59. package/dist/react.js.map +1 -1
  60. package/dist/renderer.cjs +503 -0
  61. package/dist/renderer.cjs.map +1 -0
  62. package/dist/renderer.d.cts +250 -0
  63. package/dist/renderer.d.ts +250 -0
  64. package/dist/renderer.js +501 -0
  65. package/dist/renderer.js.map +1 -0
  66. package/dist/rss.cjs +291 -0
  67. package/dist/rss.cjs.map +1 -0
  68. package/dist/rss.d.cts +158 -0
  69. package/dist/rss.d.ts +158 -0
  70. package/dist/rss.js +268 -0
  71. package/dist/rss.js.map +1 -0
  72. package/dist/vue.cjs +23 -2
  73. package/dist/vue.cjs.map +1 -1
  74. package/dist/vue.js +3 -2
  75. package/dist/vue.js.map +1 -1
  76. package/package.json +72 -6
package/dist/flags.cjs CHANGED
@@ -4,8 +4,14 @@
4
4
  function createFlagBridge(options) {
5
5
  return {
6
6
  isEnabled: (flagKey, userContext) => {
7
- if (!flagKey) return false;
8
- return options.isEnabled(flagKey, userContext);
7
+ const fallback = options.defaultValue ?? false;
8
+ if (!flagKey) return fallback;
9
+ try {
10
+ return options.isEnabled(flagKey, userContext);
11
+ } catch (error) {
12
+ options.onError?.(error, { bridge: "custom", flagKey });
13
+ return fallback;
14
+ }
9
15
  }
10
16
  };
11
17
  }
@@ -17,6 +23,8 @@ var LaunchDarklyBridge = class {
17
23
  this.options = options;
18
24
  }
19
25
  isEnabled(flagKey, userContext) {
26
+ const fallback = this.options.defaultValue ?? false;
27
+ if (!flagKey) return fallback;
20
28
  const defaultUser = {
21
29
  key: userContext?.traits?.id ?? userContext?.role ?? "anonymous",
22
30
  custom: {
@@ -26,8 +34,13 @@ var LaunchDarklyBridge = class {
26
34
  ...userContext?.traits ?? {}
27
35
  }
28
36
  };
29
- const user = this.options.userResolver ? this.options.userResolver(userContext) : defaultUser;
30
- return this.client.variation(flagKey, user, this.options.defaultValue ?? false);
37
+ try {
38
+ const user = this.options.userResolver ? this.options.userResolver(userContext) : defaultUser;
39
+ return this.client.variation(flagKey, user, fallback);
40
+ } catch (error) {
41
+ this.options.onError?.(error, { bridge: "launchdarkly", flagKey });
42
+ return fallback;
43
+ }
31
44
  }
32
45
  };
33
46
  var PostHogBridge = class {
@@ -38,9 +51,16 @@ var PostHogBridge = class {
38
51
  this.options = options;
39
52
  }
40
53
  isEnabled(flagKey, userContext) {
41
- const distinctId = this.options.distinctIdResolver ? this.options.distinctIdResolver(userContext) : typeof userContext?.traits?.id === "string" ? userContext.traits.id : void 0;
42
- const groups = this.options.groupsResolver ? this.options.groupsResolver(userContext) : void 0;
43
- return this.client.isFeatureEnabled(flagKey, distinctId, groups, userContext?.traits);
54
+ const fallback = this.options.defaultValue ?? false;
55
+ if (!flagKey) return fallback;
56
+ try {
57
+ const distinctId = this.options.distinctIdResolver ? this.options.distinctIdResolver(userContext) : typeof userContext?.traits?.id === "string" ? userContext.traits.id : void 0;
58
+ const groups = this.options.groupsResolver ? this.options.groupsResolver(userContext) : void 0;
59
+ return this.client.isFeatureEnabled(flagKey, distinctId, groups, userContext?.traits);
60
+ } catch (error) {
61
+ this.options.onError?.(error, { bridge: "posthog", flagKey });
62
+ return fallback;
63
+ }
44
64
  }
45
65
  };
46
66
 
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/flags.ts"],"names":[],"mappings":";;;AAMO,SAAS,iBAAiB,OAAA,EAAqD;AACpF,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,CAAC,OAAA,EAAiB,WAAA,KAA8B;AACzD,MAAA,IAAI,CAAC,SAAS,OAAO,KAAA;AACrB,MAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,OAAA,EAAS,WAAW,CAAA;AAAA,IAC/C;AAAA,GACF;AACF;AAWO,IAAM,qBAAN,MAAsD;AAAA,EAC1C,MAAA;AAAA,EACA,OAAA;AAAA,EAEjB,WAAA,CAAY,MAAA,EAAgC,OAAA,GAAqC,EAAC,EAAG;AACnF,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,SAAA,CAAU,SAAiB,WAAA,EAAoC;AAC7D,IAAA,MAAM,WAAA,GAAc;AAAA,MAClB,GAAA,EAAK,WAAA,EAAa,MAAA,EAAQ,EAAA,IAAM,aAAa,IAAA,IAAQ,WAAA;AAAA,MACrD,MAAA,EAAQ;AAAA,QACN,MAAM,WAAA,EAAa,IAAA;AAAA,QACnB,MAAM,WAAA,EAAa,IAAA;AAAA,QACnB,QAAQ,WAAA,EAAa,MAAA;AAAA,QACrB,GAAI,WAAA,EAAa,MAAA,IAAU;AAAC;AAC9B,KACF;AACA,IAAA,MAAM,IAAA,GAAO,KAAK,OAAA,CAAQ,YAAA,GAAe,KAAK,OAAA,CAAQ,YAAA,CAAa,WAAW,CAAA,GAAI,WAAA;AAClF,IAAA,OAAO,IAAA,CAAK,OAAO,SAAA,CAAU,OAAA,EAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,gBAAgB,KAAK,CAAA;AAAA,EAChF;AACF;AAgBO,IAAM,gBAAN,MAAiD;AAAA,EACrC,MAAA;AAAA,EACA,OAAA;AAAA,EAEjB,WAAA,CAAY,MAAA,EAA2B,OAAA,GAAgC,EAAC,EAAG;AACzE,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,SAAA,CAAU,SAAiB,WAAA,EAAoC;AAC7D,IAAA,MAAM,aAAa,IAAA,CAAK,OAAA,CAAQ,kBAAA,GAC5B,IAAA,CAAK,QAAQ,kBAAA,CAAmB,WAAW,CAAA,GAC1C,OAAO,aAAa,MAAA,EAAQ,EAAA,KAAO,QAAA,GAAW,WAAA,CAAY,OAAO,EAAA,GAAK,MAAA;AAC3E,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,CAAQ,cAAA,GACxB,KAAK,OAAA,CAAQ,cAAA,CAAe,WAAW,CAAA,GACvC,MAAA;AACJ,IAAA,OAAO,KAAK,MAAA,CAAO,gBAAA,CAAiB,SAAS,UAAA,EAAY,MAAA,EAAQ,aAAa,MAAM,CAAA;AAAA,EACtF;AACF","file":"flags.cjs","sourcesContent":["import type { FeatureFlagBridge, UserContext } from \"./types\";\n\nexport interface CreateFlagBridgeOptions {\n isEnabled: (flagKey: string, userContext?: UserContext) => boolean;\n}\n\nexport function createFlagBridge(options: CreateFlagBridgeOptions): FeatureFlagBridge {\n return {\n isEnabled: (flagKey: string, userContext?: UserContext) => {\n if (!flagKey) return false;\n return options.isEnabled(flagKey, userContext);\n },\n };\n}\n\nexport interface LaunchDarklyClientLike {\n variation: (flagKey: string, user: Record<string, unknown>, defaultValue: boolean) => boolean;\n}\n\nexport interface LaunchDarklyBridgeOptions {\n userResolver?: (userContext?: UserContext) => Record<string, unknown>;\n defaultValue?: boolean;\n}\n\nexport class LaunchDarklyBridge implements FeatureFlagBridge {\n private readonly client: LaunchDarklyClientLike;\n private readonly options: LaunchDarklyBridgeOptions;\n\n constructor(client: LaunchDarklyClientLike, options: LaunchDarklyBridgeOptions = {}) {\n this.client = client;\n this.options = options;\n }\n\n isEnabled(flagKey: string, userContext?: UserContext): boolean {\n const defaultUser = {\n key: userContext?.traits?.id ?? userContext?.role ?? \"anonymous\",\n custom: {\n plan: userContext?.plan,\n role: userContext?.role,\n region: userContext?.region,\n ...(userContext?.traits ?? {}),\n },\n };\n const user = this.options.userResolver ? this.options.userResolver(userContext) : defaultUser;\n return this.client.variation(flagKey, user, this.options.defaultValue ?? false);\n }\n}\n\nexport interface PostHogClientLike {\n isFeatureEnabled: (\n flagKey: string,\n distinctId?: string,\n groups?: Record<string, string>,\n personProperties?: Record<string, unknown>,\n ) => boolean;\n}\n\nexport interface PostHogBridgeOptions {\n distinctIdResolver?: (userContext?: UserContext) => string | undefined;\n groupsResolver?: (userContext?: UserContext) => Record<string, string> | undefined;\n}\n\nexport class PostHogBridge implements FeatureFlagBridge {\n private readonly client: PostHogClientLike;\n private readonly options: PostHogBridgeOptions;\n\n constructor(client: PostHogClientLike, options: PostHogBridgeOptions = {}) {\n this.client = client;\n this.options = options;\n }\n\n isEnabled(flagKey: string, userContext?: UserContext): boolean {\n const distinctId = this.options.distinctIdResolver\n ? this.options.distinctIdResolver(userContext)\n : (typeof userContext?.traits?.id === \"string\" ? userContext.traits.id : undefined);\n const groups = this.options.groupsResolver\n ? this.options.groupsResolver(userContext)\n : undefined;\n return this.client.isFeatureEnabled(flagKey, distinctId, groups, userContext?.traits);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/flags.ts"],"names":[],"mappings":";;;AAQO,SAAS,iBAAiB,OAAA,EAAqD;AACpF,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,CAAC,OAAA,EAAiB,WAAA,KAA8B;AACzD,MAAA,MAAM,QAAA,GAAW,QAAQ,YAAA,IAAgB,KAAA;AACzC,MAAA,IAAI,CAAC,SAAS,OAAO,QAAA;AACrB,MAAA,IAAI;AACF,QAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,OAAA,EAAS,WAAW,CAAA;AAAA,MAC/C,SAAS,KAAA,EAAgB;AACvB,QAAA,OAAA,CAAQ,UAAU,KAAA,EAAO,EAAE,MAAA,EAAQ,QAAA,EAAU,SAAS,CAAA;AACtD,QAAA,OAAO,QAAA;AAAA,MACT;AAAA,IACF;AAAA,GACF;AACF;AAYO,IAAM,qBAAN,MAAsD;AAAA,EAC1C,MAAA;AAAA,EACA,OAAA;AAAA,EAEjB,WAAA,CAAY,MAAA,EAAgC,OAAA,GAAqC,EAAC,EAAG;AACnF,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,SAAA,CAAU,SAAiB,WAAA,EAAoC;AAC7D,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,YAAA,IAAgB,KAAA;AAC9C,IAAA,IAAI,CAAC,SAAS,OAAO,QAAA;AACrB,IAAA,MAAM,WAAA,GAAc;AAAA,MAClB,GAAA,EAAK,WAAA,EAAa,MAAA,EAAQ,EAAA,IAAM,aAAa,IAAA,IAAQ,WAAA;AAAA,MACrD,MAAA,EAAQ;AAAA,QACN,MAAM,WAAA,EAAa,IAAA;AAAA,QACnB,MAAM,WAAA,EAAa,IAAA;AAAA,QACnB,QAAQ,WAAA,EAAa,MAAA;AAAA,QACrB,GAAI,WAAA,EAAa,MAAA,IAAU;AAAC;AAC9B,KACF;AACA,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,KAAK,OAAA,CAAQ,YAAA,GAAe,KAAK,OAAA,CAAQ,YAAA,CAAa,WAAW,CAAA,GAAI,WAAA;AAClF,MAAA,OAAO,IAAA,CAAK,MAAA,CAAO,SAAA,CAAU,OAAA,EAAS,MAAM,QAAQ,CAAA;AAAA,IACtD,SAAS,KAAA,EAAgB;AACvB,MAAA,IAAA,CAAK,QAAQ,OAAA,GAAU,KAAA,EAAO,EAAE,MAAA,EAAQ,cAAA,EAAgB,SAAS,CAAA;AACjE,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,EACF;AACF;AAkBO,IAAM,gBAAN,MAAiD;AAAA,EACrC,MAAA;AAAA,EACA,OAAA;AAAA,EAEjB,WAAA,CAAY,MAAA,EAA2B,OAAA,GAAgC,EAAC,EAAG;AACzE,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,SAAA,CAAU,SAAiB,WAAA,EAAoC;AAC7D,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,OAAA,CAAQ,YAAA,IAAgB,KAAA;AAC9C,IAAA,IAAI,CAAC,SAAS,OAAO,QAAA;AACrB,IAAA,IAAI;AACF,MAAA,MAAM,aAAa,IAAA,CAAK,OAAA,CAAQ,kBAAA,GAC5B,IAAA,CAAK,QAAQ,kBAAA,CAAmB,WAAW,CAAA,GAC1C,OAAO,aAAa,MAAA,EAAQ,EAAA,KAAO,QAAA,GAAW,WAAA,CAAY,OAAO,EAAA,GAAK,KAAA,CAAA;AAC3E,MAAA,MAAM,MAAA,GAAS,KAAK,OAAA,CAAQ,cAAA,GACxB,KAAK,OAAA,CAAQ,cAAA,CAAe,WAAW,CAAA,GACvC,KAAA,CAAA;AACJ,MAAA,OAAO,KAAK,MAAA,CAAO,gBAAA,CAAiB,SAAS,UAAA,EAAY,MAAA,EAAQ,aAAa,MAAM,CAAA;AAAA,IACtF,SAAS,KAAA,EAAgB;AACvB,MAAA,IAAA,CAAK,QAAQ,OAAA,GAAU,KAAA,EAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,SAAS,CAAA;AAC5D,MAAA,OAAO,QAAA;AAAA,IACT;AAAA,EACF;AACF","file":"flags.cjs","sourcesContent":["import type { FeatureFlagBridge, UserContext } from \"./types\";\n\nexport interface CreateFlagBridgeOptions {\n isEnabled: (flagKey: string, userContext?: UserContext) => boolean;\n defaultValue?: boolean;\n onError?: (error: unknown, context: { bridge: \"custom\"; flagKey: string }) => void;\n}\n\nexport function createFlagBridge(options: CreateFlagBridgeOptions): FeatureFlagBridge {\n return {\n isEnabled: (flagKey: string, userContext?: UserContext) => {\n const fallback = options.defaultValue ?? false;\n if (!flagKey) return fallback;\n try {\n return options.isEnabled(flagKey, userContext);\n } catch (error: unknown) {\n options.onError?.(error, { bridge: \"custom\", flagKey });\n return fallback;\n }\n },\n };\n}\n\nexport interface LaunchDarklyClientLike {\n variation: (flagKey: string, user: Record<string, unknown>, defaultValue: boolean) => boolean;\n}\n\nexport interface LaunchDarklyBridgeOptions {\n userResolver?: (userContext?: UserContext) => Record<string, unknown>;\n defaultValue?: boolean;\n onError?: (error: unknown, context: { bridge: \"launchdarkly\"; flagKey: string }) => void;\n}\n\nexport class LaunchDarklyBridge implements FeatureFlagBridge {\n private readonly client: LaunchDarklyClientLike;\n private readonly options: LaunchDarklyBridgeOptions;\n\n constructor(client: LaunchDarklyClientLike, options: LaunchDarklyBridgeOptions = {}) {\n this.client = client;\n this.options = options;\n }\n\n isEnabled(flagKey: string, userContext?: UserContext): boolean {\n const fallback = this.options.defaultValue ?? false;\n if (!flagKey) return fallback;\n const defaultUser = {\n key: userContext?.traits?.id ?? userContext?.role ?? \"anonymous\",\n custom: {\n plan: userContext?.plan,\n role: userContext?.role,\n region: userContext?.region,\n ...(userContext?.traits ?? {}),\n },\n };\n try {\n const user = this.options.userResolver ? this.options.userResolver(userContext) : defaultUser;\n return this.client.variation(flagKey, user, fallback);\n } catch (error: unknown) {\n this.options.onError?.(error, { bridge: \"launchdarkly\", flagKey });\n return fallback;\n }\n }\n}\n\nexport interface PostHogClientLike {\n isFeatureEnabled: (\n flagKey: string,\n distinctId?: string,\n groups?: Record<string, string>,\n personProperties?: Record<string, unknown>,\n ) => boolean;\n}\n\nexport interface PostHogBridgeOptions {\n distinctIdResolver?: (userContext?: UserContext) => string | undefined;\n groupsResolver?: (userContext?: UserContext) => Record<string, string> | undefined;\n defaultValue?: boolean;\n onError?: (error: unknown, context: { bridge: \"posthog\"; flagKey: string }) => void;\n}\n\nexport class PostHogBridge implements FeatureFlagBridge {\n private readonly client: PostHogClientLike;\n private readonly options: PostHogBridgeOptions;\n\n constructor(client: PostHogClientLike, options: PostHogBridgeOptions = {}) {\n this.client = client;\n this.options = options;\n }\n\n isEnabled(flagKey: string, userContext?: UserContext): boolean {\n const fallback = this.options.defaultValue ?? false;\n if (!flagKey) return fallback;\n try {\n const distinctId = this.options.distinctIdResolver\n ? this.options.distinctIdResolver(userContext)\n : (typeof userContext?.traits?.id === \"string\" ? userContext.traits.id : undefined);\n const groups = this.options.groupsResolver\n ? this.options.groupsResolver(userContext)\n : undefined;\n return this.client.isFeatureEnabled(flagKey, distinctId, groups, userContext?.traits);\n } catch (error: unknown) {\n this.options.onError?.(error, { bridge: \"posthog\", flagKey });\n return fallback;\n }\n }\n}\n"]}
package/dist/flags.d.cts CHANGED
@@ -16,6 +16,11 @@ interface FeatureFlagBridge {
16
16
 
17
17
  interface CreateFlagBridgeOptions {
18
18
  isEnabled: (flagKey: string, userContext?: UserContext) => boolean;
19
+ defaultValue?: boolean;
20
+ onError?: (error: unknown, context: {
21
+ bridge: "custom";
22
+ flagKey: string;
23
+ }) => void;
19
24
  }
20
25
  declare function createFlagBridge(options: CreateFlagBridgeOptions): FeatureFlagBridge;
21
26
  interface LaunchDarklyClientLike {
@@ -24,6 +29,10 @@ interface LaunchDarklyClientLike {
24
29
  interface LaunchDarklyBridgeOptions {
25
30
  userResolver?: (userContext?: UserContext) => Record<string, unknown>;
26
31
  defaultValue?: boolean;
32
+ onError?: (error: unknown, context: {
33
+ bridge: "launchdarkly";
34
+ flagKey: string;
35
+ }) => void;
27
36
  }
28
37
  declare class LaunchDarklyBridge implements FeatureFlagBridge {
29
38
  private readonly client;
@@ -37,6 +46,11 @@ interface PostHogClientLike {
37
46
  interface PostHogBridgeOptions {
38
47
  distinctIdResolver?: (userContext?: UserContext) => string | undefined;
39
48
  groupsResolver?: (userContext?: UserContext) => Record<string, string> | undefined;
49
+ defaultValue?: boolean;
50
+ onError?: (error: unknown, context: {
51
+ bridge: "posthog";
52
+ flagKey: string;
53
+ }) => void;
40
54
  }
41
55
  declare class PostHogBridge implements FeatureFlagBridge {
42
56
  private readonly client;
package/dist/flags.d.ts CHANGED
@@ -16,6 +16,11 @@ interface FeatureFlagBridge {
16
16
 
17
17
  interface CreateFlagBridgeOptions {
18
18
  isEnabled: (flagKey: string, userContext?: UserContext) => boolean;
19
+ defaultValue?: boolean;
20
+ onError?: (error: unknown, context: {
21
+ bridge: "custom";
22
+ flagKey: string;
23
+ }) => void;
19
24
  }
20
25
  declare function createFlagBridge(options: CreateFlagBridgeOptions): FeatureFlagBridge;
21
26
  interface LaunchDarklyClientLike {
@@ -24,6 +29,10 @@ interface LaunchDarklyClientLike {
24
29
  interface LaunchDarklyBridgeOptions {
25
30
  userResolver?: (userContext?: UserContext) => Record<string, unknown>;
26
31
  defaultValue?: boolean;
32
+ onError?: (error: unknown, context: {
33
+ bridge: "launchdarkly";
34
+ flagKey: string;
35
+ }) => void;
27
36
  }
28
37
  declare class LaunchDarklyBridge implements FeatureFlagBridge {
29
38
  private readonly client;
@@ -37,6 +46,11 @@ interface PostHogClientLike {
37
46
  interface PostHogBridgeOptions {
38
47
  distinctIdResolver?: (userContext?: UserContext) => string | undefined;
39
48
  groupsResolver?: (userContext?: UserContext) => Record<string, string> | undefined;
49
+ defaultValue?: boolean;
50
+ onError?: (error: unknown, context: {
51
+ bridge: "posthog";
52
+ flagKey: string;
53
+ }) => void;
40
54
  }
41
55
  declare class PostHogBridge implements FeatureFlagBridge {
42
56
  private readonly client;
package/dist/flags.js CHANGED
@@ -2,8 +2,14 @@
2
2
  function createFlagBridge(options) {
3
3
  return {
4
4
  isEnabled: (flagKey, userContext) => {
5
- if (!flagKey) return false;
6
- return options.isEnabled(flagKey, userContext);
5
+ const fallback = options.defaultValue ?? false;
6
+ if (!flagKey) return fallback;
7
+ try {
8
+ return options.isEnabled(flagKey, userContext);
9
+ } catch (error) {
10
+ options.onError?.(error, { bridge: "custom", flagKey });
11
+ return fallback;
12
+ }
7
13
  }
8
14
  };
9
15
  }
@@ -15,6 +21,8 @@ var LaunchDarklyBridge = class {
15
21
  this.options = options;
16
22
  }
17
23
  isEnabled(flagKey, userContext) {
24
+ const fallback = this.options.defaultValue ?? false;
25
+ if (!flagKey) return fallback;
18
26
  const defaultUser = {
19
27
  key: userContext?.traits?.id ?? userContext?.role ?? "anonymous",
20
28
  custom: {
@@ -24,8 +32,13 @@ var LaunchDarklyBridge = class {
24
32
  ...userContext?.traits ?? {}
25
33
  }
26
34
  };
27
- const user = this.options.userResolver ? this.options.userResolver(userContext) : defaultUser;
28
- return this.client.variation(flagKey, user, this.options.defaultValue ?? false);
35
+ try {
36
+ const user = this.options.userResolver ? this.options.userResolver(userContext) : defaultUser;
37
+ return this.client.variation(flagKey, user, fallback);
38
+ } catch (error) {
39
+ this.options.onError?.(error, { bridge: "launchdarkly", flagKey });
40
+ return fallback;
41
+ }
29
42
  }
30
43
  };
31
44
  var PostHogBridge = class {
@@ -36,9 +49,16 @@ var PostHogBridge = class {
36
49
  this.options = options;
37
50
  }
38
51
  isEnabled(flagKey, userContext) {
39
- const distinctId = this.options.distinctIdResolver ? this.options.distinctIdResolver(userContext) : typeof userContext?.traits?.id === "string" ? userContext.traits.id : void 0;
40
- const groups = this.options.groupsResolver ? this.options.groupsResolver(userContext) : void 0;
41
- return this.client.isFeatureEnabled(flagKey, distinctId, groups, userContext?.traits);
52
+ const fallback = this.options.defaultValue ?? false;
53
+ if (!flagKey) return fallback;
54
+ try {
55
+ const distinctId = this.options.distinctIdResolver ? this.options.distinctIdResolver(userContext) : typeof userContext?.traits?.id === "string" ? userContext.traits.id : void 0;
56
+ const groups = this.options.groupsResolver ? this.options.groupsResolver(userContext) : void 0;
57
+ return this.client.isFeatureEnabled(flagKey, distinctId, groups, userContext?.traits);
58
+ } catch (error) {
59
+ this.options.onError?.(error, { bridge: "posthog", flagKey });
60
+ return fallback;
61
+ }
42
62
  }
43
63
  };
44
64
 
package/dist/flags.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/flags.ts"],"names":[],"mappings":";AAMO,SAAS,iBAAiB,OAAA,EAAqD;AACpF,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,CAAC,OAAA,EAAiB,WAAA,KAA8B;AACzD,MAAA,IAAI,CAAC,SAAS,OAAO,KAAA;AACrB,MAAA,OAAO,OAAA,CAAQ,SAAA,CAAU,OAAA,EAAS,WAAW,CAAA;AAAA,IAC/C;AAAA,GACF;AACF;AAWO,IAAM,qBAAN,MAAsD;AAAA,EAC1C,MAAA;AAAA,EACA,OAAA;AAAA,EAEjB,WAAA,CAAY,MAAA,EAAgC,OAAA,GAAqC,EAAC,EAAG;AACnF,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,SAAA,CAAU,SAAiB,WAAA,EAAoC;AAC7D,IAAA,MAAM,WAAA,GAAc;AAAA,MAClB,GAAA,EAAK,WAAA,EAAa,MAAA,EAAQ,EAAA,IAAM,aAAa,IAAA,IAAQ,WAAA;AAAA,MACrD,MAAA,EAAQ;AAAA,QACN,MAAM,WAAA,EAAa,IAAA;AAAA,QACnB,MAAM,WAAA,EAAa,IAAA;AAAA,QACnB,QAAQ,WAAA,EAAa,MAAA;AAAA,QACrB,GAAI,WAAA,EAAa,MAAA,IAAU;AAAC;AAC9B,KACF;AACA,IAAA,MAAM,IAAA,GAAO,KAAK,OAAA,CAAQ,YAAA,GAAe,KAAK,OAAA,CAAQ,YAAA,CAAa,WAAW,CAAA,GAAI,WAAA;AAClF,IAAA,OAAO,IAAA,CAAK,OAAO,SAAA,CAAU,OAAA,EAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,gBAAgB,KAAK,CAAA;AAAA,EAChF;AACF;AAgBO,IAAM,gBAAN,MAAiD;AAAA,EACrC,MAAA;AAAA,EACA,OAAA;AAAA,EAEjB,WAAA,CAAY,MAAA,EAA2B,OAAA,GAAgC,EAAC,EAAG;AACzE,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,SAAA,CAAU,SAAiB,WAAA,EAAoC;AAC7D,IAAA,MAAM,aAAa,IAAA,CAAK,OAAA,CAAQ,kBAAA,GAC5B,IAAA,CAAK,QAAQ,kBAAA,CAAmB,WAAW,CAAA,GAC1C,OAAO,aAAa,MAAA,EAAQ,EAAA,KAAO,QAAA,GAAW,WAAA,CAAY,OAAO,EAAA,GAAK,MAAA;AAC3E,IAAA,MAAM,MAAA,GAAS,KAAK,OAAA,CAAQ,cAAA,GACxB,KAAK,OAAA,CAAQ,cAAA,CAAe,WAAW,CAAA,GACvC,MAAA;AACJ,IAAA,OAAO,KAAK,MAAA,CAAO,gBAAA,CAAiB,SAAS,UAAA,EAAY,MAAA,EAAQ,aAAa,MAAM,CAAA;AAAA,EACtF;AACF","file":"flags.js","sourcesContent":["import type { FeatureFlagBridge, UserContext } from \"./types\";\n\nexport interface CreateFlagBridgeOptions {\n isEnabled: (flagKey: string, userContext?: UserContext) => boolean;\n}\n\nexport function createFlagBridge(options: CreateFlagBridgeOptions): FeatureFlagBridge {\n return {\n isEnabled: (flagKey: string, userContext?: UserContext) => {\n if (!flagKey) return false;\n return options.isEnabled(flagKey, userContext);\n },\n };\n}\n\nexport interface LaunchDarklyClientLike {\n variation: (flagKey: string, user: Record<string, unknown>, defaultValue: boolean) => boolean;\n}\n\nexport interface LaunchDarklyBridgeOptions {\n userResolver?: (userContext?: UserContext) => Record<string, unknown>;\n defaultValue?: boolean;\n}\n\nexport class LaunchDarklyBridge implements FeatureFlagBridge {\n private readonly client: LaunchDarklyClientLike;\n private readonly options: LaunchDarklyBridgeOptions;\n\n constructor(client: LaunchDarklyClientLike, options: LaunchDarklyBridgeOptions = {}) {\n this.client = client;\n this.options = options;\n }\n\n isEnabled(flagKey: string, userContext?: UserContext): boolean {\n const defaultUser = {\n key: userContext?.traits?.id ?? userContext?.role ?? \"anonymous\",\n custom: {\n plan: userContext?.plan,\n role: userContext?.role,\n region: userContext?.region,\n ...(userContext?.traits ?? {}),\n },\n };\n const user = this.options.userResolver ? this.options.userResolver(userContext) : defaultUser;\n return this.client.variation(flagKey, user, this.options.defaultValue ?? false);\n }\n}\n\nexport interface PostHogClientLike {\n isFeatureEnabled: (\n flagKey: string,\n distinctId?: string,\n groups?: Record<string, string>,\n personProperties?: Record<string, unknown>,\n ) => boolean;\n}\n\nexport interface PostHogBridgeOptions {\n distinctIdResolver?: (userContext?: UserContext) => string | undefined;\n groupsResolver?: (userContext?: UserContext) => Record<string, string> | undefined;\n}\n\nexport class PostHogBridge implements FeatureFlagBridge {\n private readonly client: PostHogClientLike;\n private readonly options: PostHogBridgeOptions;\n\n constructor(client: PostHogClientLike, options: PostHogBridgeOptions = {}) {\n this.client = client;\n this.options = options;\n }\n\n isEnabled(flagKey: string, userContext?: UserContext): boolean {\n const distinctId = this.options.distinctIdResolver\n ? this.options.distinctIdResolver(userContext)\n : (typeof userContext?.traits?.id === \"string\" ? userContext.traits.id : undefined);\n const groups = this.options.groupsResolver\n ? this.options.groupsResolver(userContext)\n : undefined;\n return this.client.isFeatureEnabled(flagKey, distinctId, groups, userContext?.traits);\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/flags.ts"],"names":[],"mappings":"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","file":"flags.js","sourcesContent":["import type { FeatureFlagBridge, UserContext } from \"./types\";\n\nexport interface CreateFlagBridgeOptions {\n isEnabled: (flagKey: string, userContext?: UserContext) => boolean;\n defaultValue?: boolean;\n onError?: (error: unknown, context: { bridge: \"custom\"; flagKey: string }) => void;\n}\n\nexport function createFlagBridge(options: CreateFlagBridgeOptions): FeatureFlagBridge {\n return {\n isEnabled: (flagKey: string, userContext?: UserContext) => {\n const fallback = options.defaultValue ?? false;\n if (!flagKey) return fallback;\n try {\n return options.isEnabled(flagKey, userContext);\n } catch (error: unknown) {\n options.onError?.(error, { bridge: \"custom\", flagKey });\n return fallback;\n }\n },\n };\n}\n\nexport interface LaunchDarklyClientLike {\n variation: (flagKey: string, user: Record<string, unknown>, defaultValue: boolean) => boolean;\n}\n\nexport interface LaunchDarklyBridgeOptions {\n userResolver?: (userContext?: UserContext) => Record<string, unknown>;\n defaultValue?: boolean;\n onError?: (error: unknown, context: { bridge: \"launchdarkly\"; flagKey: string }) => void;\n}\n\nexport class LaunchDarklyBridge implements FeatureFlagBridge {\n private readonly client: LaunchDarklyClientLike;\n private readonly options: LaunchDarklyBridgeOptions;\n\n constructor(client: LaunchDarklyClientLike, options: LaunchDarklyBridgeOptions = {}) {\n this.client = client;\n this.options = options;\n }\n\n isEnabled(flagKey: string, userContext?: UserContext): boolean {\n const fallback = this.options.defaultValue ?? false;\n if (!flagKey) return fallback;\n const defaultUser = {\n key: userContext?.traits?.id ?? userContext?.role ?? \"anonymous\",\n custom: {\n plan: userContext?.plan,\n role: userContext?.role,\n region: userContext?.region,\n ...(userContext?.traits ?? {}),\n },\n };\n try {\n const user = this.options.userResolver ? this.options.userResolver(userContext) : defaultUser;\n return this.client.variation(flagKey, user, fallback);\n } catch (error: unknown) {\n this.options.onError?.(error, { bridge: \"launchdarkly\", flagKey });\n return fallback;\n }\n }\n}\n\nexport interface PostHogClientLike {\n isFeatureEnabled: (\n flagKey: string,\n distinctId?: string,\n groups?: Record<string, string>,\n personProperties?: Record<string, unknown>,\n ) => boolean;\n}\n\nexport interface PostHogBridgeOptions {\n distinctIdResolver?: (userContext?: UserContext) => string | undefined;\n groupsResolver?: (userContext?: UserContext) => Record<string, string> | undefined;\n defaultValue?: boolean;\n onError?: (error: unknown, context: { bridge: \"posthog\"; flagKey: string }) => void;\n}\n\nexport class PostHogBridge implements FeatureFlagBridge {\n private readonly client: PostHogClientLike;\n private readonly options: PostHogBridgeOptions;\n\n constructor(client: PostHogClientLike, options: PostHogBridgeOptions = {}) {\n this.client = client;\n this.options = options;\n }\n\n isEnabled(flagKey: string, userContext?: UserContext): boolean {\n const fallback = this.options.defaultValue ?? false;\n if (!flagKey) return fallback;\n try {\n const distinctId = this.options.distinctIdResolver\n ? this.options.distinctIdResolver(userContext)\n : (typeof userContext?.traits?.id === \"string\" ? userContext.traits.id : undefined);\n const groups = this.options.groupsResolver\n ? this.options.groupsResolver(userContext)\n : undefined;\n return this.client.isFeatureEnabled(flagKey, distinctId, groups, userContext?.traits);\n } catch (error: unknown) {\n this.options.onError?.(error, { bridge: \"posthog\", flagKey });\n return fallback;\n }\n }\n}\n"]}