@posthog/convex 0.2.33 → 1.0.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 (53) hide show
  1. package/README.md +132 -16
  2. package/dist/client/feature-flags/crypto.d.ts +2 -0
  3. package/dist/client/feature-flags/crypto.d.ts.map +1 -0
  4. package/dist/client/feature-flags/crypto.js +11 -0
  5. package/dist/client/feature-flags/crypto.js.map +1 -0
  6. package/dist/client/feature-flags/evaluator.d.ts +47 -0
  7. package/dist/client/feature-flags/evaluator.d.ts.map +1 -0
  8. package/dist/client/feature-flags/evaluator.js +346 -0
  9. package/dist/client/feature-flags/evaluator.js.map +1 -0
  10. package/dist/client/feature-flags/index.d.ts +4 -0
  11. package/dist/client/feature-flags/index.d.ts.map +1 -0
  12. package/dist/client/feature-flags/index.js +3 -0
  13. package/dist/client/feature-flags/index.js.map +1 -0
  14. package/dist/client/feature-flags/match-property.d.ts +12 -0
  15. package/dist/client/feature-flags/match-property.d.ts.map +1 -0
  16. package/dist/client/feature-flags/match-property.js +340 -0
  17. package/dist/client/feature-flags/match-property.js.map +1 -0
  18. package/dist/client/feature-flags/types.d.ts +63 -0
  19. package/dist/client/feature-flags/types.d.ts.map +1 -0
  20. package/dist/client/feature-flags/types.js +2 -0
  21. package/dist/client/feature-flags/types.js.map +1 -0
  22. package/dist/client/index.d.ts +71 -36
  23. package/dist/client/index.d.ts.map +1 -1
  24. package/dist/client/index.js +143 -32
  25. package/dist/client/index.js.map +1 -1
  26. package/dist/component/_generated/component.d.ts +8 -35
  27. package/dist/component/_generated/component.d.ts.map +1 -1
  28. package/dist/component/lib.d.ts +76 -46
  29. package/dist/component/lib.d.ts.map +1 -1
  30. package/dist/component/lib.js +311 -99
  31. package/dist/component/lib.js.map +1 -1
  32. package/dist/component/schema.d.ts +18 -1
  33. package/dist/component/schema.d.ts.map +1 -1
  34. package/dist/component/schema.js +16 -2
  35. package/dist/component/schema.js.map +1 -1
  36. package/dist/component/version.d.ts +2 -0
  37. package/dist/component/version.d.ts.map +1 -0
  38. package/dist/component/version.js +2 -0
  39. package/dist/component/version.js.map +1 -0
  40. package/package.json +5 -5
  41. package/src/client/feature-flags/crypto.ts +12 -0
  42. package/src/client/feature-flags/evaluator.test.ts +401 -0
  43. package/src/client/feature-flags/evaluator.ts +467 -0
  44. package/src/client/feature-flags/index.ts +15 -0
  45. package/src/client/feature-flags/match-property.test.ts +75 -0
  46. package/src/client/feature-flags/match-property.ts +347 -0
  47. package/src/client/feature-flags/types.ts +72 -0
  48. package/src/client/index.test.ts +60 -12
  49. package/src/client/index.ts +227 -70
  50. package/src/component/_generated/component.ts +7 -50
  51. package/src/component/lib.ts +340 -127
  52. package/src/component/schema.ts +16 -2
  53. package/src/component/version.ts +1 -0
@@ -1,20 +1,28 @@
1
1
  import type { Scheduler } from 'convex/server'
2
2
  import type { ComponentApi } from '../component/_generated/component.js'
3
+ import {
4
+ type FeatureFlagResult,
5
+ type FeatureFlagValue,
6
+ type FlagDefinitions,
7
+ type JsonType,
8
+ LocalFeatureFlagEvaluator,
9
+ } from './feature-flags/index.js'
3
10
 
4
11
  /** Context with a scheduler — available in mutations and actions. */
5
12
  type SchedulerCtx = { scheduler: Scheduler }
6
13
 
7
- /** Context with runAction — available in actions only. */
8
- type ActionCtx = { runAction: (reference: any, args: any) => Promise<any> }
14
+ /** Context with runQuery — available in queries, mutations, and actions. */
15
+ type RunQueryCtx = { runQuery: (reference: any, args: any) => Promise<any> }
9
16
 
10
17
  type FeatureFlagOptions = {
11
18
  groups?: Record<string, string>
12
- personProperties?: Record<string, string>
13
- groupProperties?: Record<string, Record<string, string>>
14
- sendFeatureFlagEvents?: boolean
19
+ personProperties?: Record<string, any>
20
+ groupProperties?: Record<string, Record<string, any>>
15
21
  disableGeoip?: boolean
16
22
  }
17
23
 
24
+ type AllFlagsOptions = FeatureFlagOptions & { flagKeys?: string[] }
25
+
18
26
  const DEFAULT_HOST = 'https://us.i.posthog.com'
19
27
 
20
28
  function normalizeApiKey(value?: unknown): string {
@@ -26,12 +34,7 @@ function normalizeHost(value?: unknown): string {
26
34
  return normalizedValue || DEFAULT_HOST
27
35
  }
28
36
 
29
- export type FeatureFlagResult = {
30
- key: string
31
- enabled: boolean
32
- variant: string | null
33
- payload: unknown
34
- }
37
+ export type { FeatureFlagResult, FeatureFlagValue, JsonType }
35
38
 
36
39
  export type PostHogEvent = {
37
40
  event: string
@@ -74,8 +77,12 @@ export function normalizeError(error: unknown): {
74
77
  return { message: String(error) }
75
78
  }
76
79
 
80
+ /** Context with runAction — available in actions. Used by `refreshFlagDefinitions`. */
81
+ type RunActionCtx = { runAction: (reference: any, args: any) => Promise<any> }
82
+
77
83
  export class PostHog {
78
84
  private apiKey: string
85
+ private personalApiKey: string
79
86
  private host: string
80
87
  private beforeSend?: BeforeSendFn | BeforeSendFn[]
81
88
  private identifyFn?: IdentifyFn
@@ -84,17 +91,40 @@ export class PostHog {
84
91
  public component: ComponentApi,
85
92
  options?: {
86
93
  apiKey?: string
94
+ /**
95
+ * Either a [feature flags secure API key](https://posthog.com/docs/feature-flags/local-evaluation#step-1-find-your-feature-flags-secure-api-key)
96
+ * (`phs_…`, recommended) or a personal API key (`phx_…`) with feature-flag read access.
97
+ * Required for local feature flag evaluation; defaults to `process.env.POSTHOG_PERSONAL_API_KEY`.
98
+ * The key is captured at construction time and forwarded to the component whenever you call
99
+ * `refreshFlagDefinitions(ctx)`.
100
+ */
101
+ personalApiKey?: string
87
102
  host?: string
88
103
  beforeSend?: BeforeSendFn | BeforeSendFn[]
89
104
  identify?: IdentifyFn
90
105
  }
91
106
  ) {
92
107
  this.apiKey = normalizeApiKey(options?.apiKey ?? process.env.POSTHOG_API_KEY)
108
+ this.personalApiKey = normalizeApiKey(options?.personalApiKey ?? process.env.POSTHOG_PERSONAL_API_KEY)
93
109
  this.host = normalizeHost(options?.host ?? process.env.POSTHOG_HOST)
94
110
  this.beforeSend = options?.beforeSend
95
111
  this.identifyFn = options?.identify
96
112
  }
97
113
 
114
+ /**
115
+ * Trigger a refresh of the cached feature flag definitions. Must be called from an action
116
+ * context (typically a cron handler) — the component fetches `/flags/definitions` and writes
117
+ * the result to its singleton table. Returns the component's status object so callers can log
118
+ * misconfiguration without throwing.
119
+ */
120
+ async refreshFlagDefinitions(ctx: RunActionCtx): Promise<unknown> {
121
+ return await ctx.runAction(this.component.lib.refreshFlagDefinitions, {
122
+ apiKey: this.apiKey,
123
+ personalApiKey: this.personalApiKey,
124
+ host: this.host,
125
+ })
126
+ }
127
+
98
128
  private async resolveDistinctId(ctx: unknown, argsDistinctId?: string): Promise<string> {
99
129
  if (this.identifyFn) {
100
130
  const result = await this.identifyFn(ctx)
@@ -118,6 +148,23 @@ export class PostHog {
118
148
  return result
119
149
  }
120
150
 
151
+ private async loadEvaluator(ctx: RunQueryCtx): Promise<LocalFeatureFlagEvaluator | null> {
152
+ const row = (await ctx.runQuery(this.component.lib.getFlagDefinitions, {})) as {
153
+ data: string
154
+ fetchedAt: number
155
+ etag?: string
156
+ } | null
157
+ if (!row) return null
158
+ let parsed: FlagDefinitions
159
+ try {
160
+ parsed = JSON.parse(row.data) as FlagDefinitions
161
+ } catch (e) {
162
+ console.warn('[PostHog] Failed to parse cached flag definitions; treating as unavailable.', e)
163
+ return null
164
+ }
165
+ return new LocalFeatureFlagEvaluator(parsed)
166
+ }
167
+
121
168
  // --- Fire-and-forget methods (work in mutations and actions) ---
122
169
 
123
170
  async capture(
@@ -207,7 +254,10 @@ export class PostHog {
207
254
  groupType: args.groupType,
208
255
  groupKey: args.groupKey,
209
256
  properties: result.properties ? JSON.stringify(result.properties) : undefined,
210
- distinctId: args.distinctId,
257
+ // Use the post-beforeSend distinctId so any mutation (redaction, remapping) is honoured.
258
+ // Fall back to undefined when the result is the empty placeholder so we don't ship "" to
259
+ // the component (which would then send `distinct_id: ""` for a group identify).
260
+ distinctId: result.distinctId || undefined,
211
261
  disableGeoip: args.disableGeoip,
212
262
  })
213
263
  }
@@ -271,104 +321,211 @@ export class PostHog {
271
321
  })
272
322
  }
273
323
 
274
- // --- Feature flag methods (require action context) ---
324
+ // --- Feature flag methods (locally evaluated; work in queries, mutations, and actions) ---
325
+ //
326
+ // All feature flag methods evaluate flags locally against the definitions cached by the
327
+ // component's cron. `undefined` signals that the eval couldn't reach a verdict — either
328
+ // definitions haven't been fetched yet (POSTHOG_PERSONAL_API_KEY missing, or the cron hasn't
329
+ // run for the first time), or the flag uses features incompatible with local evaluation
330
+ // (experience continuity, static cohorts, properties not provided). For payload methods,
331
+ // `null` is reserved for the case where the flag was evaluated but matched no payload — so
332
+ // callers can distinguish "no payload" from "eval unavailable".
275
333
 
276
334
  async getFeatureFlag(
277
- ctx: ActionCtx,
335
+ ctx: RunQueryCtx,
278
336
  args: { key: string; distinctId?: string } & FeatureFlagOptions
279
- ): Promise<boolean | string | null> {
337
+ ): Promise<FeatureFlagValue | undefined> {
280
338
  const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
281
- return await ctx.runAction(this.component.lib.getFeatureFlag, {
282
- apiKey: this.apiKey,
283
- host: this.host,
284
- ...args,
339
+ const evaluator = await this.loadEvaluator(ctx)
340
+ if (!evaluator) return undefined
341
+ return await evaluator.getFeatureFlag(
342
+ args.key,
285
343
  distinctId,
286
- })
344
+ args.groups ?? {},
345
+ args.personProperties ?? {},
346
+ args.groupProperties ?? {}
347
+ )
287
348
  }
288
349
 
289
350
  async isFeatureEnabled(
290
- ctx: ActionCtx,
351
+ ctx: RunQueryCtx,
291
352
  args: { key: string; distinctId?: string } & FeatureFlagOptions
292
- ): Promise<boolean | null> {
293
- const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
294
- return await ctx.runAction(this.component.lib.isFeatureEnabled, {
295
- apiKey: this.apiKey,
296
- host: this.host,
297
- ...args,
298
- distinctId,
299
- })
353
+ ): Promise<boolean | undefined> {
354
+ const value = await this.getFeatureFlag(ctx, args)
355
+ if (value === undefined) return undefined
356
+ return value !== false && value !== null
300
357
  }
301
358
 
302
359
  async getFeatureFlagPayload(
303
- ctx: ActionCtx,
360
+ ctx: RunQueryCtx,
304
361
  args: {
305
362
  key: string
306
363
  distinctId?: string
307
364
  matchValue?: boolean | string
308
365
  } & FeatureFlagOptions
309
- ): Promise<unknown> {
366
+ ): Promise<JsonType | null | undefined> {
367
+ const evaluator = await this.loadEvaluator(ctx)
368
+ // `undefined` means we couldn't evaluate (no definitions cached, or the evaluator returned
369
+ // inconclusive). `null` means we did evaluate and there's no payload — distinguishing the
370
+ // two lets callers handle the "definitions not loaded yet" case explicitly.
371
+ if (!evaluator) return undefined
372
+ // When a caller supplies `matchValue` the payload lookup doesn't need a distinctId — it's a
373
+ // pure key+value lookup. Defer resolution until we actually need it, so callers using the
374
+ // "look up payload for a flag value I already evaluated" pattern don't have to configure an
375
+ // identify callback or pass a distinctId they don't have.
376
+ if (args.matchValue !== undefined) {
377
+ return evaluator.getFeatureFlagPayload(args.key, '', args.matchValue)
378
+ }
310
379
  const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
311
- return await ctx.runAction(this.component.lib.getFeatureFlagPayload, {
312
- apiKey: this.apiKey,
313
- host: this.host,
314
- ...args,
380
+ return await evaluator.getFeatureFlagPayload(
381
+ args.key,
315
382
  distinctId,
316
- })
383
+ undefined,
384
+ args.groups ?? {},
385
+ args.personProperties ?? {},
386
+ args.groupProperties ?? {}
387
+ )
317
388
  }
318
389
 
319
390
  async getFeatureFlagResult(
320
- ctx: ActionCtx,
391
+ ctx: RunQueryCtx,
392
+ args: { key: string; distinctId?: string } & FeatureFlagOptions
393
+ ): Promise<FeatureFlagResult | undefined> {
394
+ const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
395
+ const evaluator = await this.loadEvaluator(ctx)
396
+ if (!evaluator) return undefined
397
+ const result = await evaluator.getFeatureFlagResult(
398
+ args.key,
399
+ distinctId,
400
+ args.groups ?? {},
401
+ args.personProperties ?? {},
402
+ args.groupProperties ?? {}
403
+ )
404
+ if (!result) return undefined
405
+ // `null` isn't in `FeatureFlagValue`'s declared type but the evaluator handles it defensively
406
+ // in several places (payload lookup, flag-dependency cache). Treat it as a disabled value
407
+ // here so a stray `null` can't slip through as `enabled: true, variant: null`.
408
+ if (result.value === false || result.value === null) {
409
+ return { key: args.key, enabled: false, variant: null, payload: result.payload ?? null }
410
+ }
411
+ return {
412
+ key: args.key,
413
+ enabled: true,
414
+ variant: typeof result.value === 'string' ? result.value : null,
415
+ payload: result.payload ?? null,
416
+ }
417
+ }
418
+
419
+ async getAllFlags(
420
+ ctx: RunQueryCtx,
421
+ args: { distinctId?: string } & AllFlagsOptions
422
+ ): Promise<Record<string, FeatureFlagValue>> {
423
+ const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
424
+ const evaluator = await this.loadEvaluator(ctx)
425
+ if (!evaluator) return {}
426
+ const { featureFlags } = await evaluator.getAllFlagsAndPayloads(
427
+ distinctId,
428
+ args.groups ?? {},
429
+ args.personProperties ?? {},
430
+ args.groupProperties ?? {},
431
+ args.flagKeys
432
+ )
433
+ return featureFlags
434
+ }
435
+
436
+ async getAllFlagsAndPayloads(
437
+ ctx: RunQueryCtx,
438
+ args: { distinctId?: string } & AllFlagsOptions
439
+ ): Promise<{
440
+ featureFlags: Record<string, FeatureFlagValue>
441
+ featureFlagPayloads: Record<string, JsonType>
442
+ }> {
443
+ const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
444
+ const evaluator = await this.loadEvaluator(ctx)
445
+ if (!evaluator) return { featureFlags: {}, featureFlagPayloads: {} }
446
+ return await evaluator.getAllFlagsAndPayloads(
447
+ distinctId,
448
+ args.groups ?? {},
449
+ args.personProperties ?? {},
450
+ args.groupProperties ?? {},
451
+ args.flagKeys
452
+ )
453
+ }
454
+
455
+ // --- Remote feature flag evaluation (action context) ---
456
+ //
457
+ // For flags that can't be evaluated locally — experience continuity, static cohorts,
458
+ // properties you can't pass in — or when you haven't configured a personal API key. These
459
+ // hit PostHog's `/flags` endpoint via a component action, so they require an action ctx and
460
+ // incur a per-call network round trip.
461
+
462
+ /**
463
+ * Evaluate a single flag remotely against PostHog's `/flags` endpoint. Action context only.
464
+ * Returns the flag value, or `null` if the flag doesn't exist.
465
+ */
466
+ async evaluateFlag(
467
+ ctx: RunActionCtx,
321
468
  args: { key: string; distinctId?: string } & FeatureFlagOptions
322
- ): Promise<FeatureFlagResult | null> {
469
+ ): Promise<FeatureFlagValue | null> {
323
470
  const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
324
- return await ctx.runAction(this.component.lib.getFeatureFlagResult, {
471
+ return (await ctx.runAction(this.component.lib.evaluateFlag, {
325
472
  apiKey: this.apiKey,
326
473
  host: this.host,
327
- ...args,
474
+ key: args.key,
328
475
  distinctId,
329
- })
476
+ groups: args.groups,
477
+ personProperties: args.personProperties,
478
+ groupProperties: args.groupProperties,
479
+ disableGeoip: args.disableGeoip,
480
+ })) as FeatureFlagValue | null
330
481
  }
331
482
 
332
- async getAllFlags(
333
- ctx: ActionCtx,
334
- args: {
335
- distinctId?: string
336
- groups?: Record<string, string>
337
- personProperties?: Record<string, string>
338
- groupProperties?: Record<string, Record<string, string>>
339
- disableGeoip?: boolean
340
- flagKeys?: string[]
341
- }
342
- ): Promise<Record<string, boolean | string>> {
483
+ /**
484
+ * Evaluate a single flag's payload remotely against PostHog's `/flags` endpoint. Action context
485
+ * only. Returns the payload, or `null` if the flag doesn't match or has no payload configured.
486
+ */
487
+ async evaluateFlagPayload(
488
+ ctx: RunActionCtx,
489
+ args: { key: string; distinctId?: string } & FeatureFlagOptions
490
+ ): Promise<JsonType | null> {
343
491
  const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
344
- return await ctx.runAction(this.component.lib.getAllFlags, {
492
+ return (await ctx.runAction(this.component.lib.evaluateFlagPayload, {
345
493
  apiKey: this.apiKey,
346
494
  host: this.host,
347
- ...args,
495
+ key: args.key,
348
496
  distinctId,
349
- })
497
+ groups: args.groups,
498
+ personProperties: args.personProperties,
499
+ groupProperties: args.groupProperties,
500
+ disableGeoip: args.disableGeoip,
501
+ })) as JsonType | null
350
502
  }
351
503
 
352
- async getAllFlagsAndPayloads(
353
- ctx: ActionCtx,
354
- args: {
355
- distinctId?: string
356
- groups?: Record<string, string>
357
- personProperties?: Record<string, string>
358
- groupProperties?: Record<string, Record<string, string>>
359
- disableGeoip?: boolean
360
- flagKeys?: string[]
361
- }
504
+ /**
505
+ * Evaluate every flag for the user remotely in one `/flags` request. Action context only.
506
+ * Returns both `featureFlags` (key → value) and `featureFlagPayloads` (key → payload). Use
507
+ * `flagKeys` to scope the request to a specific subset.
508
+ */
509
+ async evaluateAllFlags(
510
+ ctx: RunActionCtx,
511
+ args: { distinctId?: string } & AllFlagsOptions
362
512
  ): Promise<{
363
- featureFlags: Record<string, boolean | string>
364
- featureFlagPayloads: Record<string, unknown>
513
+ featureFlags: Record<string, FeatureFlagValue>
514
+ featureFlagPayloads: Record<string, JsonType>
365
515
  }> {
366
516
  const distinctId = await this.resolveDistinctId(ctx, args.distinctId)
367
- return await ctx.runAction(this.component.lib.getAllFlagsAndPayloads, {
517
+ return (await ctx.runAction(this.component.lib.evaluateAllFlags, {
368
518
  apiKey: this.apiKey,
369
519
  host: this.host,
370
- ...args,
371
520
  distinctId,
372
- })
521
+ groups: args.groups,
522
+ personProperties: args.personProperties,
523
+ groupProperties: args.groupProperties,
524
+ disableGeoip: args.disableGeoip,
525
+ flagKeys: args.flagKeys,
526
+ })) as {
527
+ featureFlags: Record<string, FeatureFlagValue>
528
+ featureFlagPayloads: Record<string, JsonType>
529
+ }
373
530
  }
374
531
  }
@@ -70,7 +70,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
70
70
  any,
71
71
  Name
72
72
  >;
73
- getAllFlags: FunctionReference<
73
+ evaluateAllFlags: FunctionReference<
74
74
  "action",
75
75
  "internal",
76
76
  {
@@ -86,7 +86,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
86
86
  any,
87
87
  Name
88
88
  >;
89
- getAllFlagsAndPayloads: FunctionReference<
89
+ evaluateFlag: FunctionReference<
90
90
  "action",
91
91
  "internal",
92
92
  {
@@ -97,63 +97,30 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
97
97
  groupProperties?: any;
98
98
  groups?: any;
99
99
  host: string;
100
- personProperties?: any;
101
- },
102
- any,
103
- Name
104
- >;
105
- getFeatureFlag: FunctionReference<
106
- "action",
107
- "internal",
108
- {
109
- apiKey: string;
110
- disableGeoip?: boolean;
111
- distinctId: string;
112
- groupProperties?: any;
113
- groups?: any;
114
- host: string;
115
- key: string;
116
- personProperties?: any;
117
- sendFeatureFlagEvents?: boolean;
118
- },
119
- any,
120
- Name
121
- >;
122
- getFeatureFlagPayload: FunctionReference<
123
- "action",
124
- "internal",
125
- {
126
- apiKey: string;
127
- disableGeoip?: boolean;
128
- distinctId: string;
129
- groupProperties?: any;
130
- groups?: any;
131
- host: string;
132
100
  key: string;
133
- matchValue?: string | boolean;
134
101
  personProperties?: any;
135
- sendFeatureFlagEvents?: boolean;
136
102
  },
137
103
  any,
138
104
  Name
139
105
  >;
140
- getFeatureFlagResult: FunctionReference<
106
+ evaluateFlagPayload: FunctionReference<
141
107
  "action",
142
108
  "internal",
143
109
  {
144
110
  apiKey: string;
145
111
  disableGeoip?: boolean;
146
112
  distinctId: string;
113
+ flagKeys?: Array<string>;
147
114
  groupProperties?: any;
148
115
  groups?: any;
149
116
  host: string;
150
117
  key: string;
151
118
  personProperties?: any;
152
- sendFeatureFlagEvents?: boolean;
153
119
  },
154
120
  any,
155
121
  Name
156
122
  >;
123
+ getFlagDefinitions: FunctionReference<"query", "internal", {}, any, Name>;
157
124
  groupIdentify: FunctionReference<
158
125
  "action",
159
126
  "internal",
@@ -182,20 +149,10 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
182
149
  any,
183
150
  Name
184
151
  >;
185
- isFeatureEnabled: FunctionReference<
152
+ refreshFlagDefinitions: FunctionReference<
186
153
  "action",
187
154
  "internal",
188
- {
189
- apiKey: string;
190
- disableGeoip?: boolean;
191
- distinctId: string;
192
- groupProperties?: any;
193
- groups?: any;
194
- host: string;
195
- key: string;
196
- personProperties?: any;
197
- sendFeatureFlagEvents?: boolean;
198
- },
155
+ { apiKey: string; host?: string; personalApiKey: string },
199
156
  any,
200
157
  Name
201
158
  >;