@claudeye/linux-arm64 1.0.4-beta.9 → 1.0.4

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 (187) hide show
  1. package/assets/standalone/.next/BUILD_ID +1 -1
  2. package/assets/standalone/.next/build-manifest.json +2 -2
  3. package/assets/standalone/.next/prerender-manifest.json +3 -3
  4. package/assets/standalone/.next/required-server-files.json +0 -3
  5. package/assets/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  6. package/assets/standalone/.next/server/app/_global-error.html +2 -2
  7. package/assets/standalone/.next/server/app/_global-error.rsc +7 -7
  8. package/assets/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  9. package/assets/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  10. package/assets/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  11. package/assets/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  12. package/assets/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  13. package/assets/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  14. package/assets/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/assets/standalone/.next/server/app/_not-found.html +2 -2
  16. package/assets/standalone/.next/server/app/_not-found.rsc +14 -14
  17. package/assets/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +14 -14
  18. package/assets/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  19. package/assets/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +9 -9
  20. package/assets/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  21. package/assets/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  22. package/assets/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/assets/standalone/.next/server/app/api/completed-history/route.js +1 -1
  24. package/assets/standalone/.next/server/app/api/queue-item/route.js +2 -2
  25. package/assets/standalone/.next/server/app/api/queue-status/route.js +1 -1
  26. package/assets/standalone/.next/server/app/dashboard/[viewName]/page/server-reference-manifest.json +4 -4
  27. package/assets/standalone/.next/server/app/dashboard/[viewName]/page_client-reference-manifest.js +1 -1
  28. package/assets/standalone/.next/server/app/dashboard/page/server-reference-manifest.json +4 -4
  29. package/assets/standalone/.next/server/app/dashboard/page_client-reference-manifest.js +1 -1
  30. package/assets/standalone/.next/server/app/login/page/server-reference-manifest.json +2 -2
  31. package/assets/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
  32. package/assets/standalone/.next/server/app/login.html +2 -2
  33. package/assets/standalone/.next/server/app/login.rsc +15 -15
  34. package/assets/standalone/.next/server/app/login.segments/_full.segment.rsc +15 -15
  35. package/assets/standalone/.next/server/app/login.segments/_head.segment.rsc +4 -4
  36. package/assets/standalone/.next/server/app/login.segments/_index.segment.rsc +9 -9
  37. package/assets/standalone/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  38. package/assets/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +4 -4
  39. package/assets/standalone/.next/server/app/login.segments/login.segment.rsc +3 -3
  40. package/assets/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
  41. package/assets/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  42. package/assets/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
  43. package/assets/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
  44. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
  45. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +8 -8
  46. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +1 -1
  47. package/assets/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
  48. package/assets/standalone/.next/server/app/queue/page/server-reference-manifest.json +3 -3
  49. package/assets/standalone/.next/server/app/queue/page.js +2 -2
  50. package/assets/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
  51. package/assets/standalone/.next/server/chunks/{[externals]_next_dist_db0236a7._.js → [externals]__06cd15c5._.js} +2 -2
  52. package/assets/standalone/.next/server/chunks/[externals]__10373a08._.js +3 -0
  53. package/assets/standalone/.next/server/chunks/[externals]__d78bcb54._.js +3 -0
  54. package/assets/standalone/.next/server/chunks/[root-of-the-server]__067f11b8._.js +3 -0
  55. package/assets/standalone/.next/server/chunks/[root-of-the-server]__22ffcb4e._.js +3 -0
  56. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__3232b9b5._.js → [root-of-the-server]__292809cf._.js} +1 -1
  57. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__bf0c3d33._.js → [root-of-the-server]__3c3ad1da._.js} +4 -4
  58. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__6d076258._.js → [root-of-the-server]__43c4e0bc._.js} +1 -1
  59. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__6fc9da2e._.js → [root-of-the-server]__7c44135a._.js} +1 -1
  60. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__ffb39c82._.js → [root-of-the-server]__939bf5b3._.js} +2 -2
  61. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__fe48bb1c._.js → [root-of-the-server]__bd194a73._.js} +2 -2
  62. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__b2f1c82c._.js → [root-of-the-server]__ca12b24d._.js} +2 -2
  63. package/assets/standalone/.next/server/chunks/[root-of-the-server]__d7355d04._.js +1 -1
  64. package/assets/standalone/.next/server/chunks/{[root-of-the-server]__255e6fbc._.js → [root-of-the-server]__dcb3f873._.js} +1 -1
  65. package/assets/standalone/.next/server/chunks/[root-of-the-server]__e3e9ab09._.js +4 -0
  66. package/assets/standalone/.next/server/chunks/[root-of-the-server]__f26a70d1._.js +3 -0
  67. package/assets/standalone/.next/server/chunks/_3f3c09bf._.js +1 -1
  68. package/assets/standalone/.next/server/chunks/_5336fde9._.js +3 -0
  69. package/assets/standalone/.next/server/chunks/_7e07bbd9._.js +1 -1
  70. package/assets/standalone/.next/server/chunks/_8f856fad._.js +1 -1
  71. package/assets/standalone/.next/server/chunks/{_717db053._.js → _b7316450._.js} +1 -1
  72. package/assets/standalone/.next/server/chunks/_b8adaa37._.js +2 -2
  73. package/assets/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_7a66d362.js +1 -1
  74. package/assets/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_05ab10df._.js +3 -0
  75. package/assets/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_20debb74._.js +3 -0
  76. package/assets/standalone/.next/server/chunks/package_json_4b1b4d6f._.js +1 -1
  77. package/assets/standalone/.next/server/chunks/ssr/[externals]__10373a08._.js +3 -0
  78. package/assets/standalone/.next/server/chunks/ssr/{[root-of-the-server]__16a44ef3._.js → [root-of-the-server]__acea31a9._.js} +3 -3
  79. package/assets/standalone/.next/server/chunks/ssr/{[root-of-the-server]__10ac3567._.js → [root-of-the-server]__c3591792._.js} +3 -3
  80. package/assets/standalone/.next/server/chunks/ssr/_14858238._.js +1 -1
  81. package/assets/standalone/.next/server/chunks/ssr/_19a3e694._.js +2 -2
  82. package/assets/standalone/.next/server/chunks/ssr/_1d335924._.js +1 -1
  83. package/assets/standalone/.next/server/chunks/ssr/_3dacef09._.js +1 -1
  84. package/assets/standalone/.next/server/chunks/ssr/_617143fc._.js +2 -2
  85. package/assets/standalone/.next/server/chunks/ssr/_76ab933f._.js +1 -1
  86. package/assets/standalone/.next/server/chunks/ssr/_7ae321cd._.js +2 -2
  87. package/assets/standalone/.next/server/chunks/ssr/_87e025a1._.js +1 -1
  88. package/assets/standalone/.next/server/chunks/ssr/_986c0cdb._.js +2 -2
  89. package/assets/standalone/.next/server/chunks/ssr/_c9400c33._.js +2 -2
  90. package/assets/standalone/.next/server/chunks/ssr/_d7159840._.js +1 -1
  91. package/assets/standalone/.next/server/chunks/ssr/_fa9c2bed._.js +2 -2
  92. package/assets/standalone/.next/server/chunks/ssr/app_actions_compute-dashboard_ts_fc151dbb._.js +1 -1
  93. package/assets/standalone/.next/server/chunks/ssr/app_login_page_tsx_ccc0019b._.js +1 -1
  94. package/assets/standalone/.next/server/chunks/ssr/app_queue_queue-client_tsx_45f040f7._.js +1 -1
  95. package/assets/standalone/.next/server/chunks/ssr/node_modules_next_dist_274ac3eb._.js +1 -1
  96. package/assets/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_8222e100._.js +3 -0
  97. package/assets/standalone/.next/server/instrumentation.js +1 -1
  98. package/assets/standalone/.next/server/middleware.js +2 -2
  99. package/assets/standalone/.next/server/pages/404.html +2 -2
  100. package/assets/standalone/.next/server/pages/500.html +2 -2
  101. package/assets/standalone/.next/server/server-reference-manifest.js +1 -1
  102. package/assets/standalone/.next/server/server-reference-manifest.json +15 -15
  103. package/assets/standalone/.next/static/chunks/{723f2367261046f4.js → 11f25fc2615691ff.js} +1 -1
  104. package/assets/standalone/.next/static/chunks/{98ef6309c816722d.css → 14b2a22c2d5f76c5.css} +1 -1
  105. package/assets/standalone/.next/static/chunks/{d2be314c3ece3fbe.js → 2b423cf30d3964a3.js} +1 -1
  106. package/assets/standalone/.next/static/chunks/{97c295191089a1c2.js → 5920eabcfc97a878.js} +1 -1
  107. package/assets/standalone/.next/static/chunks/{dbec35204e8940b4.js → 6f48312d9fefe6e7.js} +1 -1
  108. package/assets/standalone/.next/static/chunks/8da8518dc46b9734.js +1 -0
  109. package/assets/standalone/.next/static/chunks/91129b8c2a80b1b2.js +4 -0
  110. package/assets/standalone/.next/static/chunks/{fd8c1fc19ac30592.js → 96e6f5987bb7f381.js} +3 -3
  111. package/assets/standalone/.next/static/chunks/{27fc246b001f7ba2.js → ef5e745c131e6572.js} +1 -1
  112. package/assets/standalone/instrumentation.node.ts +54 -0
  113. package/assets/standalone/package.json +3 -2
  114. package/assets/standalone/server.js +1 -1
  115. package/bin/claudeye +0 -0
  116. package/package.json +1 -1
  117. package/assets/standalone/.next/server/chunks/[externals]_posthog-node_4a68be38._.js +0 -3
  118. package/assets/standalone/.next/server/chunks/[root-of-the-server]__19c9c5af._.js +0 -4
  119. package/assets/standalone/.next/server/chunks/[root-of-the-server]__365c750b._.js +0 -3
  120. package/assets/standalone/.next/server/chunks/[root-of-the-server]__4ea757c2._.js +0 -3
  121. package/assets/standalone/.next/server/chunks/[root-of-the-server]__c84cf1dc._.js +0 -3
  122. package/assets/standalone/.next/server/chunks/ssr/[externals]_posthog-node_4a68be38._.js +0 -3
  123. package/assets/standalone/.next/static/chunks/13ab76b2fb94bd45.js +0 -1
  124. package/assets/standalone/.next/static/chunks/3346a6085951648c.js +0 -4
  125. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/chunk-ids.mjs +0 -34
  126. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/dom-exception-coercer.mjs +0 -31
  127. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/error-coercer.mjs +0 -27
  128. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/error-event-coercer.mjs +0 -18
  129. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/event-coercer.mjs +0 -17
  130. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/index.mjs +0 -8
  131. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/object-coercer.mjs +0 -51
  132. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/primitive-coercer.mjs +0 -15
  133. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/promise-rejection-event.mjs +0 -25
  134. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/string-coercer.mjs +0 -29
  135. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/coercers/utils.mjs +0 -18
  136. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/error-properties-builder.mjs +0 -112
  137. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/index.mjs +0 -4
  138. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/parsers/base.mjs +0 -14
  139. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/parsers/chrome.mjs +0 -27
  140. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/parsers/gecko.mjs +0 -24
  141. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/parsers/index.mjs +0 -47
  142. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/parsers/node.mjs +0 -65
  143. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/parsers/opera.mjs +0 -12
  144. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/parsers/safari.mjs +0 -13
  145. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/parsers/winjs.mjs +0 -7
  146. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/types.mjs +0 -9
  147. package/assets/standalone/node_modules/@posthog/core/dist/error-tracking/utils.mjs +0 -23
  148. package/assets/standalone/node_modules/@posthog/core/dist/eventemitter.mjs +0 -18
  149. package/assets/standalone/node_modules/@posthog/core/dist/featureFlagUtils.mjs +0 -113
  150. package/assets/standalone/node_modules/@posthog/core/dist/gzip.mjs +0 -18
  151. package/assets/standalone/node_modules/@posthog/core/dist/index.mjs +0 -9
  152. package/assets/standalone/node_modules/@posthog/core/dist/posthog-core-stateless.mjs +0 -676
  153. package/assets/standalone/node_modules/@posthog/core/dist/posthog-core.mjs +0 -761
  154. package/assets/standalone/node_modules/@posthog/core/dist/surveys/validation.mjs +0 -33
  155. package/assets/standalone/node_modules/@posthog/core/dist/types.mjs +0 -137
  156. package/assets/standalone/node_modules/@posthog/core/dist/utils/bot-detection.mjs +0 -88
  157. package/assets/standalone/node_modules/@posthog/core/dist/utils/bucketed-rate-limiter.mjs +0 -41
  158. package/assets/standalone/node_modules/@posthog/core/dist/utils/index.mjs +0 -59
  159. package/assets/standalone/node_modules/@posthog/core/dist/utils/logger.mjs +0 -38
  160. package/assets/standalone/node_modules/@posthog/core/dist/utils/number-utils.mjs +0 -41
  161. package/assets/standalone/node_modules/@posthog/core/dist/utils/promise-queue.mjs +0 -27
  162. package/assets/standalone/node_modules/@posthog/core/dist/utils/string-utils.mjs +0 -31
  163. package/assets/standalone/node_modules/@posthog/core/dist/utils/type-utils.mjs +0 -82
  164. package/assets/standalone/node_modules/@posthog/core/dist/utils/user-agent-utils.mjs +0 -338
  165. package/assets/standalone/node_modules/@posthog/core/dist/vendor/uuidv7.mjs +0 -170
  166. package/assets/standalone/node_modules/@posthog/core/package.json +0 -69
  167. package/assets/standalone/node_modules/posthog-node/dist/client.mjs +0 -718
  168. package/assets/standalone/node_modules/posthog-node/dist/entrypoints/index.node.mjs +0 -26
  169. package/assets/standalone/node_modules/posthog-node/dist/exports.mjs +0 -5
  170. package/assets/standalone/node_modules/posthog-node/dist/extensions/context/context.mjs +0 -28
  171. package/assets/standalone/node_modules/posthog-node/dist/extensions/error-tracking/autocapture.mjs +0 -31
  172. package/assets/standalone/node_modules/posthog-node/dist/extensions/error-tracking/index.mjs +0 -69
  173. package/assets/standalone/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.js +0 -227
  174. package/assets/standalone/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs +0 -187
  175. package/assets/standalone/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.js +0 -64
  176. package/assets/standalone/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs +0 -30
  177. package/assets/standalone/node_modules/posthog-node/dist/extensions/express.mjs +0 -32
  178. package/assets/standalone/node_modules/posthog-node/dist/extensions/feature-flags/crypto.mjs +0 -8
  179. package/assets/standalone/node_modules/posthog-node/dist/extensions/feature-flags/feature-flags.mjs +0 -772
  180. package/assets/standalone/node_modules/posthog-node/dist/extensions/sentry-integration.mjs +0 -72
  181. package/assets/standalone/node_modules/posthog-node/dist/storage-memory.mjs +0 -12
  182. package/assets/standalone/node_modules/posthog-node/dist/types.mjs +0 -7
  183. package/assets/standalone/node_modules/posthog-node/dist/version.mjs +0 -2
  184. package/assets/standalone/node_modules/posthog-node/package.json +0 -105
  185. /package/assets/standalone/.next/static/{J4fam3sTS7cM1hFzhpIJy → ooDwT_B4qzYMdxRb-wV62}/_buildManifest.js +0 -0
  186. /package/assets/standalone/.next/static/{J4fam3sTS7cM1hFzhpIJy → ooDwT_B4qzYMdxRb-wV62}/_clientMiddlewareManifest.json +0 -0
  187. /package/assets/standalone/.next/static/{J4fam3sTS7cM1hFzhpIJy → ooDwT_B4qzYMdxRb-wV62}/_ssgManifest.js +0 -0
@@ -1,772 +0,0 @@
1
- import { safeSetTimeout } from "@posthog/core";
2
- import { hashSHA1 } from "./crypto.mjs";
3
- const SIXTY_SECONDS = 60000;
4
- const LONG_SCALE = 0xfffffffffffffff;
5
- const NULL_VALUES_ALLOWED_OPERATORS = [
6
- 'is_not'
7
- ];
8
- class ClientError extends Error {
9
- constructor(message){
10
- super();
11
- Error.captureStackTrace(this, this.constructor);
12
- this.name = 'ClientError';
13
- this.message = message;
14
- Object.setPrototypeOf(this, ClientError.prototype);
15
- }
16
- }
17
- class InconclusiveMatchError extends Error {
18
- constructor(message){
19
- super(message);
20
- this.name = this.constructor.name;
21
- Error.captureStackTrace(this, this.constructor);
22
- Object.setPrototypeOf(this, InconclusiveMatchError.prototype);
23
- }
24
- }
25
- class RequiresServerEvaluation extends Error {
26
- constructor(message){
27
- super(message);
28
- this.name = this.constructor.name;
29
- Error.captureStackTrace(this, this.constructor);
30
- Object.setPrototypeOf(this, RequiresServerEvaluation.prototype);
31
- }
32
- }
33
- class FeatureFlagsPoller {
34
- constructor({ pollingInterval, personalApiKey, projectApiKey, timeout, host, customHeaders, ...options }){
35
- this.debugMode = false;
36
- this.shouldBeginExponentialBackoff = false;
37
- this.backOffCount = 0;
38
- this.pollingInterval = pollingInterval;
39
- this.personalApiKey = personalApiKey;
40
- this.featureFlags = [];
41
- this.featureFlagsByKey = {};
42
- this.groupTypeMapping = {};
43
- this.cohorts = {};
44
- this.loadedSuccessfullyOnce = false;
45
- this.timeout = timeout;
46
- this.projectApiKey = projectApiKey;
47
- this.host = host;
48
- this.poller = void 0;
49
- this.fetch = options.fetch || fetch;
50
- this.onError = options.onError;
51
- this.customHeaders = customHeaders;
52
- this.onLoad = options.onLoad;
53
- this.cacheProvider = options.cacheProvider;
54
- this.strictLocalEvaluation = options.strictLocalEvaluation ?? false;
55
- this.loadFeatureFlags();
56
- }
57
- debug(enabled = true) {
58
- this.debugMode = enabled;
59
- }
60
- logMsgIfDebug(fn) {
61
- if (this.debugMode) fn();
62
- }
63
- createEvaluationContext(distinctId, groups = {}, personProperties = {}, groupProperties = {}, evaluationCache = {}) {
64
- return {
65
- distinctId,
66
- groups,
67
- personProperties,
68
- groupProperties,
69
- evaluationCache
70
- };
71
- }
72
- async getFeatureFlag(key, distinctId, groups = {}, personProperties = {}, groupProperties = {}) {
73
- await this.loadFeatureFlags();
74
- let response;
75
- let featureFlag;
76
- if (!this.loadedSuccessfullyOnce) return response;
77
- featureFlag = this.featureFlagsByKey[key];
78
- if (void 0 !== featureFlag) {
79
- const evaluationContext = this.createEvaluationContext(distinctId, groups, personProperties, groupProperties);
80
- try {
81
- const result = await this.computeFlagAndPayloadLocally(featureFlag, evaluationContext);
82
- response = result.value;
83
- this.logMsgIfDebug(()=>console.debug(`Successfully computed flag locally: ${key} -> ${response}`));
84
- } catch (e) {
85
- if (e instanceof RequiresServerEvaluation || e instanceof InconclusiveMatchError) this.logMsgIfDebug(()=>console.debug(`${e.name} when computing flag locally: ${key}: ${e.message}`));
86
- else if (e instanceof Error) this.onError?.(new Error(`Error computing flag locally: ${key}: ${e}`));
87
- }
88
- }
89
- return response;
90
- }
91
- async getAllFlagsAndPayloads(evaluationContext, flagKeysToExplicitlyEvaluate) {
92
- await this.loadFeatureFlags();
93
- const response = {};
94
- const payloads = {};
95
- let fallbackToFlags = 0 == this.featureFlags.length;
96
- const flagsToEvaluate = flagKeysToExplicitlyEvaluate ? flagKeysToExplicitlyEvaluate.map((key)=>this.featureFlagsByKey[key]).filter(Boolean) : this.featureFlags;
97
- const sharedEvaluationContext = {
98
- ...evaluationContext,
99
- evaluationCache: evaluationContext.evaluationCache ?? {}
100
- };
101
- await Promise.all(flagsToEvaluate.map(async (flag)=>{
102
- try {
103
- const { value: matchValue, payload: matchPayload } = await this.computeFlagAndPayloadLocally(flag, sharedEvaluationContext);
104
- response[flag.key] = matchValue;
105
- if (matchPayload) payloads[flag.key] = matchPayload;
106
- } catch (e) {
107
- if (e instanceof RequiresServerEvaluation || e instanceof InconclusiveMatchError) this.logMsgIfDebug(()=>console.debug(`${e.name} when computing flag locally: ${flag.key}: ${e.message}`));
108
- else if (e instanceof Error) this.onError?.(new Error(`Error computing flag locally: ${flag.key}: ${e}`));
109
- fallbackToFlags = true;
110
- }
111
- }));
112
- return {
113
- response,
114
- payloads,
115
- fallbackToFlags
116
- };
117
- }
118
- async computeFlagAndPayloadLocally(flag, evaluationContext, options = {}) {
119
- const { matchValue, skipLoadCheck = false } = options;
120
- if (!skipLoadCheck) await this.loadFeatureFlags();
121
- if (!this.loadedSuccessfullyOnce) return {
122
- value: false,
123
- payload: null
124
- };
125
- let flagValue;
126
- flagValue = void 0 !== matchValue ? matchValue : await this.computeFlagValueLocally(flag, evaluationContext);
127
- const payload = this.getFeatureFlagPayload(flag.key, flagValue);
128
- return {
129
- value: flagValue,
130
- payload
131
- };
132
- }
133
- async computeFlagValueLocally(flag, evaluationContext) {
134
- const { distinctId, groups, personProperties, groupProperties } = evaluationContext;
135
- if (flag.ensure_experience_continuity) throw new InconclusiveMatchError('Flag has experience continuity enabled');
136
- if (!flag.active) return false;
137
- const flagFilters = flag.filters || {};
138
- const aggregation_group_type_index = flagFilters.aggregation_group_type_index;
139
- if (void 0 != aggregation_group_type_index) {
140
- const groupName = this.groupTypeMapping[String(aggregation_group_type_index)];
141
- if (!groupName) {
142
- this.logMsgIfDebug(()=>console.warn(`[FEATURE FLAGS] Unknown group type index ${aggregation_group_type_index} for feature flag ${flag.key}`));
143
- throw new InconclusiveMatchError('Flag has unknown group type index');
144
- }
145
- if (!(groupName in groups)) {
146
- this.logMsgIfDebug(()=>console.warn(`[FEATURE FLAGS] Can't compute group feature flag: ${flag.key} without group names passed in`));
147
- return false;
148
- }
149
- if ('device_id' === flag.bucketing_identifier && (personProperties?.$device_id === void 0 || personProperties?.$device_id === null || personProperties?.$device_id === '')) this.logMsgIfDebug(()=>console.warn(`[FEATURE FLAGS] Ignoring bucketing_identifier for group flag: ${flag.key}`));
150
- const focusedGroupProperties = groupProperties[groupName];
151
- return await this.matchFeatureFlagProperties(flag, groups[groupName], focusedGroupProperties, evaluationContext);
152
- }
153
- {
154
- const bucketingValue = this.getBucketingValueForFlag(flag, distinctId, personProperties);
155
- if (void 0 === bucketingValue) {
156
- this.logMsgIfDebug(()=>console.warn(`[FEATURE FLAGS] Can't compute feature flag: ${flag.key} without $device_id, falling back to server evaluation`));
157
- throw new InconclusiveMatchError(`Can't compute feature flag: ${flag.key} without $device_id`);
158
- }
159
- return await this.matchFeatureFlagProperties(flag, bucketingValue, personProperties, evaluationContext);
160
- }
161
- }
162
- getBucketingValueForFlag(flag, distinctId, properties) {
163
- if (flag.filters?.aggregation_group_type_index != void 0) return distinctId;
164
- if ('device_id' === flag.bucketing_identifier) {
165
- const deviceId = properties?.$device_id;
166
- if (null == deviceId || '' === deviceId) return;
167
- return deviceId;
168
- }
169
- return distinctId;
170
- }
171
- getFeatureFlagPayload(key, flagValue) {
172
- let payload = null;
173
- if (false !== flagValue && null != flagValue) {
174
- if ('boolean' == typeof flagValue) payload = this.featureFlagsByKey?.[key]?.filters?.payloads?.[flagValue.toString()] || null;
175
- else if ('string' == typeof flagValue) payload = this.featureFlagsByKey?.[key]?.filters?.payloads?.[flagValue] || null;
176
- if (null != payload) {
177
- if ('object' == typeof payload) return payload;
178
- if ('string' == typeof payload) try {
179
- return JSON.parse(payload);
180
- } catch {}
181
- return payload;
182
- }
183
- }
184
- return null;
185
- }
186
- async evaluateFlagDependency(property, properties, evaluationContext) {
187
- const { evaluationCache } = evaluationContext;
188
- const targetFlagKey = property.key;
189
- if (!this.featureFlagsByKey) throw new InconclusiveMatchError('Feature flags not available for dependency evaluation');
190
- if (!('dependency_chain' in property)) throw new InconclusiveMatchError(`Flag dependency property for '${targetFlagKey}' is missing required 'dependency_chain' field`);
191
- const dependencyChain = property.dependency_chain;
192
- if (!Array.isArray(dependencyChain)) throw new InconclusiveMatchError(`Flag dependency property for '${targetFlagKey}' has an invalid 'dependency_chain' (expected array, got ${typeof dependencyChain})`);
193
- if (0 === dependencyChain.length) throw new InconclusiveMatchError(`Circular dependency detected for flag '${targetFlagKey}' (empty dependency chain)`);
194
- for (const depFlagKey of dependencyChain){
195
- if (!(depFlagKey in evaluationCache)) {
196
- const depFlag = this.featureFlagsByKey[depFlagKey];
197
- if (depFlag) if (depFlag.active) try {
198
- const depResult = await this.computeFlagValueLocally(depFlag, evaluationContext);
199
- evaluationCache[depFlagKey] = depResult;
200
- } catch (error) {
201
- throw new InconclusiveMatchError(`Error evaluating flag dependency '${depFlagKey}' for flag '${targetFlagKey}': ${error}`);
202
- }
203
- else evaluationCache[depFlagKey] = false;
204
- else throw new InconclusiveMatchError(`Missing flag dependency '${depFlagKey}' for flag '${targetFlagKey}'`);
205
- }
206
- const cachedResult = evaluationCache[depFlagKey];
207
- if (null == cachedResult) throw new InconclusiveMatchError(`Dependency '${depFlagKey}' could not be evaluated`);
208
- }
209
- const targetFlagValue = evaluationCache[targetFlagKey];
210
- return this.flagEvaluatesToExpectedValue(property.value, targetFlagValue);
211
- }
212
- flagEvaluatesToExpectedValue(expectedValue, flagValue) {
213
- if ('boolean' == typeof expectedValue) return expectedValue === flagValue || 'string' == typeof flagValue && '' !== flagValue && true === expectedValue;
214
- if ('string' == typeof expectedValue) return flagValue === expectedValue;
215
- return false;
216
- }
217
- async matchFeatureFlagProperties(flag, bucketingValue, properties, evaluationContext) {
218
- const flagFilters = flag.filters || {};
219
- const flagConditions = flagFilters.groups || [];
220
- let isInconclusive = false;
221
- let result;
222
- for (const condition of flagConditions)try {
223
- if (await this.isConditionMatch(flag, bucketingValue, condition, properties, evaluationContext)) {
224
- const variantOverride = condition.variant;
225
- const flagVariants = flagFilters.multivariate?.variants || [];
226
- result = variantOverride && flagVariants.some((variant)=>variant.key === variantOverride) ? variantOverride : await this.getMatchingVariant(flag, bucketingValue) || true;
227
- break;
228
- }
229
- } catch (e) {
230
- if (e instanceof RequiresServerEvaluation) throw e;
231
- if (e instanceof InconclusiveMatchError) isInconclusive = true;
232
- else throw e;
233
- }
234
- if (void 0 !== result) return result;
235
- if (isInconclusive) throw new InconclusiveMatchError("Can't determine if feature flag is enabled or not with given properties");
236
- return false;
237
- }
238
- async isConditionMatch(flag, bucketingValue, condition, properties, evaluationContext) {
239
- const rolloutPercentage = condition.rollout_percentage;
240
- const warnFunction = (msg)=>{
241
- this.logMsgIfDebug(()=>console.warn(msg));
242
- };
243
- if ((condition.properties || []).length > 0) {
244
- for (const prop of condition.properties){
245
- const propertyType = prop.type;
246
- let matches = false;
247
- matches = 'cohort' === propertyType ? matchCohort(prop, properties, this.cohorts, this.debugMode) : 'flag' === propertyType ? await this.evaluateFlagDependency(prop, properties, evaluationContext) : matchProperty(prop, properties, warnFunction);
248
- if (!matches) return false;
249
- }
250
- if (void 0 == rolloutPercentage) return true;
251
- }
252
- if (void 0 != rolloutPercentage && await _hash(flag.key, bucketingValue) > rolloutPercentage / 100.0) return false;
253
- return true;
254
- }
255
- async getMatchingVariant(flag, bucketingValue) {
256
- const hashValue = await _hash(flag.key, bucketingValue, 'variant');
257
- const matchingVariant = this.variantLookupTable(flag).find((variant)=>hashValue >= variant.valueMin && hashValue < variant.valueMax);
258
- if (matchingVariant) return matchingVariant.key;
259
- }
260
- variantLookupTable(flag) {
261
- const lookupTable = [];
262
- let valueMin = 0;
263
- let valueMax = 0;
264
- const flagFilters = flag.filters || {};
265
- const multivariates = flagFilters.multivariate?.variants || [];
266
- multivariates.forEach((variant)=>{
267
- valueMax = valueMin + variant.rollout_percentage / 100.0;
268
- lookupTable.push({
269
- valueMin,
270
- valueMax,
271
- key: variant.key
272
- });
273
- valueMin = valueMax;
274
- });
275
- return lookupTable;
276
- }
277
- updateFlagState(flagData) {
278
- this.featureFlags = flagData.flags;
279
- this.featureFlagsByKey = flagData.flags.reduce((acc, curr)=>(acc[curr.key] = curr, acc), {});
280
- this.groupTypeMapping = flagData.groupTypeMapping;
281
- this.cohorts = flagData.cohorts;
282
- this.loadedSuccessfullyOnce = true;
283
- }
284
- warnAboutExperienceContinuityFlags(flags) {
285
- if (this.strictLocalEvaluation) return;
286
- const experienceContinuityFlags = flags.filter((f)=>f.ensure_experience_continuity);
287
- if (experienceContinuityFlags.length > 0) console.warn(`[PostHog] You are using local evaluation but ${experienceContinuityFlags.length} flag(s) have experience continuity enabled: ${experienceContinuityFlags.map((f)=>f.key).join(', ')}. Experience continuity is incompatible with local evaluation and will cause a server request on every flag evaluation, negating local evaluation cost savings. To avoid server requests and unexpected costs, either disable experience continuity on these flags in PostHog, use strictLocalEvaluation: true in client init, or pass onlyEvaluateLocally: true per flag call (flags that cannot be evaluated locally will return undefined).`);
288
- }
289
- async loadFromCache(debugMessage) {
290
- if (!this.cacheProvider) return false;
291
- try {
292
- const cached = await this.cacheProvider.getFlagDefinitions();
293
- if (cached) {
294
- this.updateFlagState(cached);
295
- this.logMsgIfDebug(()=>console.debug(`[FEATURE FLAGS] ${debugMessage} (${cached.flags.length} flags)`));
296
- this.onLoad?.(this.featureFlags.length);
297
- this.warnAboutExperienceContinuityFlags(cached.flags);
298
- return true;
299
- }
300
- return false;
301
- } catch (err) {
302
- this.onError?.(new Error(`Failed to load from cache: ${err}`));
303
- return false;
304
- }
305
- }
306
- async loadFeatureFlags(forceReload = false) {
307
- if (this.loadedSuccessfullyOnce && !forceReload) return;
308
- if (!forceReload && this.nextFetchAllowedAt && Date.now() < this.nextFetchAllowedAt) return void this.logMsgIfDebug(()=>console.debug('[FEATURE FLAGS] Skipping fetch, in backoff period'));
309
- if (!this.loadingPromise) this.loadingPromise = this._loadFeatureFlags().catch((err)=>this.logMsgIfDebug(()=>console.debug(`[FEATURE FLAGS] Failed to load feature flags: ${err}`))).finally(()=>{
310
- this.loadingPromise = void 0;
311
- });
312
- return this.loadingPromise;
313
- }
314
- isLocalEvaluationReady() {
315
- return (this.loadedSuccessfullyOnce ?? false) && (this.featureFlags?.length ?? 0) > 0;
316
- }
317
- getFlagDefinitionsLoadedAt() {
318
- return this.flagDefinitionsLoadedAt;
319
- }
320
- getPollingInterval() {
321
- if (!this.shouldBeginExponentialBackoff) return this.pollingInterval;
322
- return Math.min(SIXTY_SECONDS, this.pollingInterval * 2 ** this.backOffCount);
323
- }
324
- beginBackoff() {
325
- this.shouldBeginExponentialBackoff = true;
326
- this.backOffCount += 1;
327
- this.nextFetchAllowedAt = Date.now() + this.getPollingInterval();
328
- }
329
- clearBackoff() {
330
- this.shouldBeginExponentialBackoff = false;
331
- this.backOffCount = 0;
332
- this.nextFetchAllowedAt = void 0;
333
- }
334
- async _loadFeatureFlags() {
335
- if (this.poller) {
336
- clearTimeout(this.poller);
337
- this.poller = void 0;
338
- }
339
- this.poller = setTimeout(()=>this.loadFeatureFlags(true), this.getPollingInterval());
340
- try {
341
- let shouldFetch = true;
342
- if (this.cacheProvider) try {
343
- shouldFetch = await this.cacheProvider.shouldFetchFlagDefinitions();
344
- } catch (err) {
345
- this.onError?.(new Error(`Error in shouldFetchFlagDefinitions: ${err}`));
346
- }
347
- if (!shouldFetch) {
348
- const loaded = await this.loadFromCache('Loaded flags from cache (skipped fetch)');
349
- if (loaded) return;
350
- if (this.loadedSuccessfullyOnce) return;
351
- }
352
- const res = await this._requestFeatureFlagDefinitions();
353
- if (!res) return;
354
- switch(res.status){
355
- case 304:
356
- this.logMsgIfDebug(()=>console.debug('[FEATURE FLAGS] Flags not modified (304), using cached data'));
357
- this.flagsEtag = res.headers?.get('ETag') ?? this.flagsEtag;
358
- this.loadedSuccessfullyOnce = true;
359
- this.clearBackoff();
360
- return;
361
- case 401:
362
- this.beginBackoff();
363
- throw new ClientError(`Your project key or personal API key is invalid. Setting next polling interval to ${this.getPollingInterval()}ms. More information: https://posthog.com/docs/api#rate-limiting`);
364
- case 402:
365
- console.warn('[FEATURE FLAGS] Feature flags quota limit exceeded - unsetting all local flags. Learn more about billing limits at https://posthog.com/docs/billing/limits-alerts');
366
- this.featureFlags = [];
367
- this.featureFlagsByKey = {};
368
- this.groupTypeMapping = {};
369
- this.cohorts = {};
370
- return;
371
- case 403:
372
- this.beginBackoff();
373
- throw new ClientError(`Your personal API key does not have permission to fetch feature flag definitions for local evaluation. Setting next polling interval to ${this.getPollingInterval()}ms. Are you sure you're using the correct personal and Project API key pair? More information: https://posthog.com/docs/api/overview`);
374
- case 429:
375
- this.beginBackoff();
376
- throw new ClientError(`You are being rate limited. Setting next polling interval to ${this.getPollingInterval()}ms. More information: https://posthog.com/docs/api#rate-limiting`);
377
- case 200:
378
- {
379
- const responseJson = await res.json() ?? {};
380
- if (!('flags' in responseJson)) return void this.onError?.(new Error(`Invalid response when getting feature flags: ${JSON.stringify(responseJson)}`));
381
- this.flagsEtag = res.headers?.get('ETag') ?? void 0;
382
- const flagData = {
383
- flags: responseJson.flags ?? [],
384
- groupTypeMapping: responseJson.group_type_mapping || {},
385
- cohorts: responseJson.cohorts || {}
386
- };
387
- this.updateFlagState(flagData);
388
- this.flagDefinitionsLoadedAt = Date.now();
389
- this.clearBackoff();
390
- if (this.cacheProvider && shouldFetch) try {
391
- await this.cacheProvider.onFlagDefinitionsReceived(flagData);
392
- } catch (err) {
393
- this.onError?.(new Error(`Failed to store in cache: ${err}`));
394
- }
395
- this.onLoad?.(this.featureFlags.length);
396
- this.warnAboutExperienceContinuityFlags(flagData.flags);
397
- break;
398
- }
399
- default:
400
- return;
401
- }
402
- } catch (err) {
403
- if (err instanceof ClientError) this.onError?.(err);
404
- }
405
- }
406
- getPersonalApiKeyRequestOptions(method = 'GET', etag) {
407
- const headers = {
408
- ...this.customHeaders,
409
- 'Content-Type': 'application/json',
410
- Authorization: `Bearer ${this.personalApiKey}`
411
- };
412
- if (etag) headers['If-None-Match'] = etag;
413
- return {
414
- method,
415
- headers
416
- };
417
- }
418
- _requestFeatureFlagDefinitions() {
419
- const url = `${this.host}/api/feature_flag/local_evaluation?token=${this.projectApiKey}&send_cohorts`;
420
- const options = this.getPersonalApiKeyRequestOptions('GET', this.flagsEtag);
421
- let abortTimeout = null;
422
- if (this.timeout && 'number' == typeof this.timeout) {
423
- const controller = new AbortController();
424
- abortTimeout = safeSetTimeout(()=>{
425
- controller.abort();
426
- }, this.timeout);
427
- options.signal = controller.signal;
428
- }
429
- try {
430
- const fetch1 = this.fetch;
431
- return fetch1(url, options);
432
- } finally{
433
- clearTimeout(abortTimeout);
434
- }
435
- }
436
- async stopPoller(timeoutMs = 30000) {
437
- clearTimeout(this.poller);
438
- if (this.cacheProvider) try {
439
- const shutdownResult = this.cacheProvider.shutdown();
440
- if (shutdownResult instanceof Promise) await Promise.race([
441
- shutdownResult,
442
- new Promise((_, reject)=>setTimeout(()=>reject(new Error(`Cache shutdown timeout after ${timeoutMs}ms`)), timeoutMs))
443
- ]);
444
- } catch (err) {
445
- this.onError?.(new Error(`Error during cache shutdown: ${err}`));
446
- }
447
- }
448
- }
449
- async function _hash(key, bucketingValue, salt = '') {
450
- const hashString = await hashSHA1(`${key}.${bucketingValue}${salt}`);
451
- return parseInt(hashString.slice(0, 15), 16) / LONG_SCALE;
452
- }
453
- function matchProperty(property, propertyValues, warnFunction) {
454
- const key = property.key;
455
- const value = property.value;
456
- const operator = property.operator || 'exact';
457
- if (key in propertyValues) {
458
- if ('is_not_set' === operator) throw new InconclusiveMatchError("Operator is_not_set is not supported");
459
- } else throw new InconclusiveMatchError(`Property ${key} not found in propertyValues`);
460
- const overrideValue = propertyValues[key];
461
- if (null == overrideValue && !NULL_VALUES_ALLOWED_OPERATORS.includes(operator)) {
462
- if (warnFunction) warnFunction(`Property ${key} cannot have a value of null/undefined with the ${operator} operator`);
463
- return false;
464
- }
465
- function computeExactMatch(value, overrideValue) {
466
- if (Array.isArray(value)) return value.map((val)=>String(val).toLowerCase()).includes(String(overrideValue).toLowerCase());
467
- return String(value).toLowerCase() === String(overrideValue).toLowerCase();
468
- }
469
- function compare(lhs, rhs, operator) {
470
- if ('gt' === operator) return lhs > rhs;
471
- if ('gte' === operator) return lhs >= rhs;
472
- if ('lt' === operator) return lhs < rhs;
473
- if ('lte' === operator) return lhs <= rhs;
474
- throw new Error(`Invalid operator: ${operator}`);
475
- }
476
- switch(operator){
477
- case 'exact':
478
- return computeExactMatch(value, overrideValue);
479
- case 'is_not':
480
- return !computeExactMatch(value, overrideValue);
481
- case 'is_set':
482
- return key in propertyValues;
483
- case 'icontains':
484
- return String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
485
- case 'not_icontains':
486
- return !String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
487
- case 'regex':
488
- return isValidRegex(String(value)) && null !== String(overrideValue).match(String(value));
489
- case 'not_regex':
490
- return isValidRegex(String(value)) && null === String(overrideValue).match(String(value));
491
- case 'gt':
492
- case 'gte':
493
- case 'lt':
494
- case 'lte':
495
- {
496
- let parsedValue = 'number' == typeof value ? value : null;
497
- if ('string' == typeof value) try {
498
- parsedValue = parseFloat(value);
499
- } catch (err) {}
500
- if (null == parsedValue || null == overrideValue) return compare(String(overrideValue), String(value), operator);
501
- if ('string' == typeof overrideValue) return compare(overrideValue, String(value), operator);
502
- return compare(overrideValue, parsedValue, operator);
503
- }
504
- case 'is_date_after':
505
- case 'is_date_before':
506
- {
507
- if ('boolean' == typeof value) throw new InconclusiveMatchError("Date operations cannot be performed on boolean values");
508
- let parsedDate = relativeDateParseForFeatureFlagMatching(String(value));
509
- if (null == parsedDate) parsedDate = convertToDateTime(value);
510
- if (null == parsedDate) throw new InconclusiveMatchError(`Invalid date: ${value}`);
511
- const overrideDate = convertToDateTime(overrideValue);
512
- if ([
513
- 'is_date_before'
514
- ].includes(operator)) return overrideDate < parsedDate;
515
- return overrideDate > parsedDate;
516
- }
517
- case 'semver_eq':
518
- {
519
- const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
520
- return 0 === cmp;
521
- }
522
- case 'semver_neq':
523
- {
524
- const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
525
- return 0 !== cmp;
526
- }
527
- case 'semver_gt':
528
- {
529
- const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
530
- return cmp > 0;
531
- }
532
- case 'semver_gte':
533
- {
534
- const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
535
- return cmp >= 0;
536
- }
537
- case 'semver_lt':
538
- {
539
- const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
540
- return cmp < 0;
541
- }
542
- case 'semver_lte':
543
- {
544
- const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
545
- return cmp <= 0;
546
- }
547
- case 'semver_tilde':
548
- {
549
- const overrideParsed = parseSemver(String(overrideValue));
550
- const { lower, upper } = computeTildeBounds(String(value));
551
- return compareSemverTuples(overrideParsed, lower) >= 0 && compareSemverTuples(overrideParsed, upper) < 0;
552
- }
553
- case 'semver_caret':
554
- {
555
- const overrideParsed = parseSemver(String(overrideValue));
556
- const { lower, upper } = computeCaretBounds(String(value));
557
- return compareSemverTuples(overrideParsed, lower) >= 0 && compareSemverTuples(overrideParsed, upper) < 0;
558
- }
559
- case 'semver_wildcard':
560
- {
561
- const overrideParsed = parseSemver(String(overrideValue));
562
- const { lower, upper } = computeWildcardBounds(String(value));
563
- return compareSemverTuples(overrideParsed, lower) >= 0 && compareSemverTuples(overrideParsed, upper) < 0;
564
- }
565
- default:
566
- throw new InconclusiveMatchError(`Unknown operator: ${operator}`);
567
- }
568
- }
569
- function checkCohortExists(cohortId, cohortProperties) {
570
- if (!(cohortId in cohortProperties)) throw new RequiresServerEvaluation(`cohort ${cohortId} not found in local cohorts - likely a static cohort that requires server evaluation`);
571
- }
572
- function matchCohort(property, propertyValues, cohortProperties, debugMode = false) {
573
- const cohortId = String(property.value);
574
- checkCohortExists(cohortId, cohortProperties);
575
- const propertyGroup = cohortProperties[cohortId];
576
- return matchPropertyGroup(propertyGroup, propertyValues, cohortProperties, debugMode);
577
- }
578
- function matchPropertyGroup(propertyGroup, propertyValues, cohortProperties, debugMode = false) {
579
- if (!propertyGroup) return true;
580
- const propertyGroupType = propertyGroup.type;
581
- const properties = propertyGroup.values;
582
- if (!properties || 0 === properties.length) return true;
583
- let errorMatchingLocally = false;
584
- if ('values' in properties[0]) {
585
- for (const prop of properties)try {
586
- const matches = matchPropertyGroup(prop, propertyValues, cohortProperties, debugMode);
587
- if ('AND' === propertyGroupType) {
588
- if (!matches) return false;
589
- } else if (matches) return true;
590
- } catch (err) {
591
- if (err instanceof RequiresServerEvaluation) throw err;
592
- if (err instanceof InconclusiveMatchError) {
593
- if (debugMode) console.debug(`Failed to compute property ${prop} locally: ${err}`);
594
- errorMatchingLocally = true;
595
- } else throw err;
596
- }
597
- if (errorMatchingLocally) throw new InconclusiveMatchError("Can't match cohort without a given cohort property value");
598
- return 'AND' === propertyGroupType;
599
- }
600
- for (const prop of properties)try {
601
- let matches;
602
- if ('cohort' === prop.type) matches = matchCohort(prop, propertyValues, cohortProperties, debugMode);
603
- else if ('flag' === prop.type) {
604
- if (debugMode) console.warn(`[FEATURE FLAGS] Flag dependency filters are not supported in local evaluation. Skipping condition with dependency on flag '${prop.key || 'unknown'}'`);
605
- continue;
606
- } else matches = matchProperty(prop, propertyValues);
607
- const negation = prop.negation || false;
608
- if ('AND' === propertyGroupType) {
609
- if (!matches && !negation) return false;
610
- if (matches && negation) return false;
611
- } else {
612
- if (matches && !negation) return true;
613
- if (!matches && negation) return true;
614
- }
615
- } catch (err) {
616
- if (err instanceof RequiresServerEvaluation) throw err;
617
- if (err instanceof InconclusiveMatchError) {
618
- if (debugMode) console.debug(`Failed to compute property ${prop} locally: ${err}`);
619
- errorMatchingLocally = true;
620
- } else throw err;
621
- }
622
- if (errorMatchingLocally) throw new InconclusiveMatchError("can't match cohort without a given cohort property value");
623
- return 'AND' === propertyGroupType;
624
- }
625
- function isValidRegex(regex) {
626
- try {
627
- new RegExp(regex);
628
- return true;
629
- } catch (err) {
630
- return false;
631
- }
632
- }
633
- function parseSemver(value) {
634
- const text = String(value).trim().replace(/^[vV]/, '');
635
- const baseVersion = text.split('-')[0].split('+')[0];
636
- if (!baseVersion || baseVersion.startsWith('.')) throw new InconclusiveMatchError(`Invalid semver: ${value}`);
637
- const parts = baseVersion.split('.');
638
- const parsePart = (part)=>{
639
- if (void 0 === part || '' === part) return 0;
640
- if (!/^\d+$/.test(part)) throw new InconclusiveMatchError(`Invalid semver: ${value}`);
641
- return parseInt(part, 10);
642
- };
643
- const major = parsePart(parts[0]);
644
- const minor = parsePart(parts[1]);
645
- const patch = parsePart(parts[2]);
646
- return [
647
- major,
648
- minor,
649
- patch
650
- ];
651
- }
652
- function compareSemverTuples(a, b) {
653
- for(let i = 0; i < 3; i++){
654
- if (a[i] < b[i]) return -1;
655
- if (a[i] > b[i]) return 1;
656
- }
657
- return 0;
658
- }
659
- function computeTildeBounds(value) {
660
- const parsed = parseSemver(value);
661
- const lower = [
662
- parsed[0],
663
- parsed[1],
664
- parsed[2]
665
- ];
666
- const upper = [
667
- parsed[0],
668
- parsed[1] + 1,
669
- 0
670
- ];
671
- return {
672
- lower,
673
- upper
674
- };
675
- }
676
- function computeCaretBounds(value) {
677
- const parsed = parseSemver(value);
678
- const [major, minor, patch] = parsed;
679
- const lower = [
680
- major,
681
- minor,
682
- patch
683
- ];
684
- let upper;
685
- upper = major > 0 ? [
686
- major + 1,
687
- 0,
688
- 0
689
- ] : minor > 0 ? [
690
- 0,
691
- minor + 1,
692
- 0
693
- ] : [
694
- 0,
695
- 0,
696
- patch + 1
697
- ];
698
- return {
699
- lower,
700
- upper
701
- };
702
- }
703
- function computeWildcardBounds(value) {
704
- const text = String(value).trim().replace(/^[vV]/, '');
705
- const cleanedText = text.replace(/\.\*$/, '').replace(/\*$/, '');
706
- if (!cleanedText) throw new InconclusiveMatchError(`Invalid wildcard semver: ${value}`);
707
- const parts = cleanedText.split('.');
708
- const major = parseInt(parts[0], 10);
709
- if (isNaN(major)) throw new InconclusiveMatchError(`Invalid wildcard semver: ${value}`);
710
- let lower;
711
- let upper;
712
- if (1 === parts.length) {
713
- lower = [
714
- major,
715
- 0,
716
- 0
717
- ];
718
- upper = [
719
- major + 1,
720
- 0,
721
- 0
722
- ];
723
- } else {
724
- const minor = parseInt(parts[1], 10);
725
- if (isNaN(minor)) throw new InconclusiveMatchError(`Invalid wildcard semver: ${value}`);
726
- lower = [
727
- major,
728
- minor,
729
- 0
730
- ];
731
- upper = [
732
- major,
733
- minor + 1,
734
- 0
735
- ];
736
- }
737
- return {
738
- lower,
739
- upper
740
- };
741
- }
742
- function convertToDateTime(value) {
743
- if (value instanceof Date) return value;
744
- if ('string' == typeof value || 'number' == typeof value) {
745
- const date = new Date(value);
746
- if (!isNaN(date.valueOf())) return date;
747
- throw new InconclusiveMatchError(`${value} is in an invalid date format`);
748
- }
749
- throw new InconclusiveMatchError(`The date provided ${value} must be a string, number, or date object`);
750
- }
751
- function relativeDateParseForFeatureFlagMatching(value) {
752
- const regex = /^-?(?<number>[0-9]+)(?<interval>[a-z])$/;
753
- const match = value.match(regex);
754
- const parsedDt = new Date(new Date().toISOString());
755
- if (!match) return null;
756
- {
757
- if (!match.groups) return null;
758
- const number = parseInt(match.groups['number']);
759
- if (number >= 10000) return null;
760
- const interval = match.groups['interval'];
761
- if ('h' == interval) parsedDt.setUTCHours(parsedDt.getUTCHours() - number);
762
- else if ('d' == interval) parsedDt.setUTCDate(parsedDt.getUTCDate() - number);
763
- else if ('w' == interval) parsedDt.setUTCDate(parsedDt.getUTCDate() - 7 * number);
764
- else if ('m' == interval) parsedDt.setUTCMonth(parsedDt.getUTCMonth() - number);
765
- else {
766
- if ('y' != interval) return null;
767
- parsedDt.setUTCFullYear(parsedDt.getUTCFullYear() - number);
768
- }
769
- return parsedDt;
770
- }
771
- }
772
- export { ClientError, FeatureFlagsPoller, InconclusiveMatchError, RequiresServerEvaluation, matchProperty, parseSemver, relativeDateParseForFeatureFlagMatching };