@getuserfeedback/protocol 0.6.1 → 0.8.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 (59) hide show
  1. package/dist/app-event.d.ts +779 -10
  2. package/dist/app-event.d.ts.map +1 -1
  3. package/dist/app-event.js +81 -8
  4. package/dist/flow-assignments.d.ts +7 -4
  5. package/dist/flow-assignments.d.ts.map +1 -1
  6. package/dist/flow-assignments.js +15 -5
  7. package/dist/host/constants.d.ts +2 -2
  8. package/dist/host/constants.d.ts.map +1 -1
  9. package/dist/host/constants.js +3 -1
  10. package/dist/host/external-id-argument-guards.d.ts +10 -0
  11. package/dist/host/external-id-argument-guards.d.ts.map +1 -0
  12. package/dist/host/external-id-argument-guards.js +27 -0
  13. package/dist/host/index.d.ts +1 -0
  14. package/dist/host/index.d.ts.map +1 -1
  15. package/dist/host/index.js +1 -0
  16. package/dist/host/sdk-types.d.ts +92 -27
  17. package/dist/host/sdk-types.d.ts.map +1 -1
  18. package/dist/host/sdk.d.ts.map +1 -1
  19. package/dist/identity-type.d.ts +2 -1
  20. package/dist/identity-type.d.ts.map +1 -1
  21. package/dist/identity-type.js +1 -1
  22. package/dist/index.d.ts +3 -87
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -6
  25. package/dist/widget-commands.d.ts +124 -3
  26. package/dist/widget-commands.d.ts.map +1 -1
  27. package/dist/widget-commands.js +10 -0
  28. package/dist/widget-config.d.ts +23 -5
  29. package/dist/widget-config.d.ts.map +1 -1
  30. package/dist/widget-config.js +2 -1
  31. package/package.json +22 -2
  32. package/src/app-event.ts +235 -0
  33. package/src/client-meta.ts +25 -0
  34. package/src/defaults.ts +4 -0
  35. package/src/errors.ts +58 -0
  36. package/src/flow-assignments.test.ts +82 -0
  37. package/src/flow-assignments.ts +151 -0
  38. package/src/host/command-dispatch.ts +59 -0
  39. package/src/host/command-envelope.ts +41 -0
  40. package/src/host/command-settlement.ts +121 -0
  41. package/src/host/constants.ts +103 -0
  42. package/src/host/external-id-argument-guards.ts +57 -0
  43. package/src/host/host-event-contract.ts +277 -0
  44. package/src/host/index.ts +14 -0
  45. package/src/host/lazy-handle-client.ts +207 -0
  46. package/src/host/request-id.ts +3 -0
  47. package/src/host/sdk-types.ts +528 -0
  48. package/src/host/sdk.ts +43 -0
  49. package/src/host/unique-id.ts +17 -0
  50. package/src/identity-type.ts +96 -0
  51. package/src/index.ts +139 -0
  52. package/src/protocol-root.test.ts +582 -0
  53. package/src/public-grant-scope.ts +25 -0
  54. package/src/runtime-endpoints.ts +69 -0
  55. package/src/scopes.ts +79 -0
  56. package/src/trpc-envelope.ts +9 -0
  57. package/src/version-resolution.ts +18 -0
  58. package/src/widget-commands.ts +162 -0
  59. package/src/widget-config.ts +164 -0
@@ -1 +1 @@
1
- {"version":3,"file":"app-event.d.ts","sourceRoot":"","sources":["../src/app-event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAG9B,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhE,eAAO,MAAM,sBAAsB;;;iBAGjC,CAAC;AAEH,KAAK,iBAAiB,GACnB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,iBAAiB,EAAE,GACnB;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAA;CAAE,CAAC;AAaxC,eAAO,MAAM,0BAA0B;;;;iBAIrC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;iBAY7B,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;iBAInC,CAAC;AAQH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMhC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM7B,CAAC;AAMH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGrC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGtC,CAAC;AAEH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG9B,CAAC;AAEH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAGhC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AACtE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACrE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC/D,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
1
+ {"version":3,"file":"app-event.d.ts","sourceRoot":"","sources":["../src/app-event.ts"],"names":[],"mappings":"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"}
package/dist/app-event.js CHANGED
@@ -13,6 +13,18 @@ const appEventFlagValueSchema = z.lazy(() => z.union([
13
13
  z.array(appEventFlagValueSchema),
14
14
  z.record(z.string(), appEventFlagValueSchema),
15
15
  ]));
16
+ const appEventJsonNumberSchema = z.number().check(z.refine(Number.isFinite, {
17
+ message: "Expected a finite JSON number.",
18
+ }));
19
+ const appEventJsonValueSchema = z.lazy(() => z.union([
20
+ z.string(),
21
+ appEventJsonNumberSchema,
22
+ z.boolean(),
23
+ z.null(),
24
+ z.array(appEventJsonValueSchema),
25
+ z.record(z.string(), appEventJsonValueSchema),
26
+ ]));
27
+ const appEventJsonObjectSchema = z.record(z.string(), appEventJsonValueSchema);
16
28
  export const appEventFlagProviderSchema = z.object({
17
29
  name: z.string().check(z.trim(), z.minLength(1)),
18
30
  project: z.optional(z.string().check(z.trim(), z.minLength(1))),
@@ -39,10 +51,20 @@ const appEventPageSchema = z.object({
39
51
  referrer: z.optional(z.string()),
40
52
  search: z.optional(z.string()),
41
53
  });
54
+ const externalIdTypeSchema = z.string().check(z.trim(), z.minLength(1), z.regex(/^[a-z0-9][a-z0-9_.-]*$/, {
55
+ message: "External ID type must start with a lowercase letter or number and may contain lowercase letters, numbers, underscores, dots, or hyphens.",
56
+ }));
57
+ export const appEventExternalIdSchema = z.object({
58
+ id: z.pipe(z.string().check(z.trim(), z.minLength(1)), z.transform((value) => value.trim())),
59
+ type: externalIdTypeSchema,
60
+ collection: z.literal("users"),
61
+ encoding: z.literal("none"),
62
+ });
42
63
  export const appEventContextSchema = z.object({
43
64
  page: z.optional(appEventPageSchema),
44
65
  locale: z.optional(z.string()),
45
66
  userAgent: z.optional(z.string()),
67
+ externalIds: z.optional(z.array(appEventExternalIdSchema).check(z.maxLength(20))),
46
68
  flags: z.optional(z.array(appEventFlagSchema)),
47
69
  capabilities: z.optional(z.array(appEventCapabilitySchema)),
48
70
  });
@@ -56,19 +78,70 @@ export const appEventBaseSchema = z.object({
56
78
  const appEventSurveyReferenceSchema = z.object({
57
79
  surveyId: z.string(),
58
80
  });
59
- export const appEventSurveyViewedSchema = z.extend(appEventBaseSchema, {
81
+ export const reservedSystemAppEventNames = [
82
+ "Response Submitted",
83
+ "Flow Viewed",
84
+ "Flow Dismissed",
85
+ "Identified",
86
+ ];
87
+ const reservedSystemAppEventNameLowercaseSet = new Set(reservedSystemAppEventNames.map((event) => event.toLowerCase()));
88
+ const appEventSystemTrackNameSchema = z.enum(["Flow Viewed", "Flow Dismissed"]);
89
+ const appEventCustomerNameSchema = z.string().check(z.trim(), z.minLength(1), z.maxLength(255), z.check((ctx) => {
90
+ if (!reservedSystemAppEventNameLowercaseSet.has(ctx.value.toLowerCase())) {
91
+ return;
92
+ }
93
+ ctx.issues.push({
94
+ code: "custom",
95
+ input: ctx.value,
96
+ message: "Customer app event names cannot use reserved system event names.",
97
+ continue: false,
98
+ });
99
+ }));
100
+ export const appEventSystemBaseSchema = z.extend(appEventBaseSchema, {
101
+ origin: z.literal("system"),
102
+ });
103
+ const normalizeSystemAppEventOrigin = (input) => {
104
+ const { origin: _origin, ...rest } = input;
105
+ return {
106
+ ...rest,
107
+ origin: "system",
108
+ };
109
+ };
110
+ export const appEventSurveyViewedSchema = z.pipe(z.extend(appEventBaseSchema, {
111
+ origin: z.optional(z.literal("system")),
60
112
  event: z.literal("Flow Viewed"),
61
113
  references: appEventSurveyReferenceSchema,
62
- });
63
- export const appEventFlowDismissedSchema = z.extend(appEventBaseSchema, {
114
+ }), z.transform(normalizeSystemAppEventOrigin));
115
+ export const appEventFlowDismissedSchema = z.pipe(z.extend(appEventBaseSchema, {
116
+ origin: z.optional(z.literal("system")),
64
117
  event: z.literal("Flow Dismissed"),
65
118
  references: appEventSurveyReferenceSchema,
119
+ }), z.transform(normalizeSystemAppEventOrigin));
120
+ export const appEventSystemTrackSchema = z.extend(appEventSystemBaseSchema, {
121
+ event: appEventSystemTrackNameSchema,
122
+ references: appEventSurveyReferenceSchema,
66
123
  });
67
- export const appEventTrackSchema = z.extend(appEventBaseSchema, {
68
- event: z.enum(["Flow Viewed", "Flow Dismissed"]),
124
+ const appEventLegacySystemTrackSchema = z.pipe(z.extend(appEventBaseSchema, {
125
+ origin: z.optional(z.literal("system")),
126
+ event: appEventSystemTrackNameSchema,
69
127
  references: appEventSurveyReferenceSchema,
128
+ }), z.transform(normalizeSystemAppEventOrigin));
129
+ export const appEventCustomerTrackSchema = z.extend(appEventBaseSchema, {
130
+ origin: z.literal("customer"),
131
+ event: appEventCustomerNameSchema,
132
+ // TODO(migration): Normalize Date values in event properties to ISO strings.
133
+ // [from=manual-date-property-serialization] [to=protocol-date-property-normalization] [scope=slice] [priority=medium] [impact=medium] [risk=low]
134
+ properties: z.optional(appEventJsonObjectSchema),
70
135
  });
71
- export const appEventPayloadSchema = z.discriminatedUnion("event", [
72
- appEventSurveyViewedSchema,
73
- appEventFlowDismissedSchema,
136
+ export const appEventTrackSchema = z.union([
137
+ appEventLegacySystemTrackSchema,
138
+ appEventCustomerTrackSchema,
139
+ ]);
140
+ const appEventDiscriminatedPayloadSchema = z.discriminatedUnion("origin", [
141
+ appEventSystemTrackSchema,
142
+ appEventCustomerTrackSchema,
143
+ ]);
144
+ export const appEventPayloadSchema = z.union([
145
+ appEventLegacySystemTrackSchema,
146
+ appEventDiscriminatedPayloadSchema,
74
147
  ]);
@@ -1,4 +1,7 @@
1
1
  import * as z from "zod/mini";
2
+ import type { IdentityTypeValue } from "./identity-type.js";
3
+ export type FlowAssignmentExternalIdIdentityTypeValue = `externalId.${string}`;
4
+ export type FlowAssignmentIdentityTypeValue = IdentityTypeValue | FlowAssignmentExternalIdIdentityTypeValue;
2
5
  export declare const flowAssignmentStatusSchema: z.ZodMiniEnum<{
3
6
  pending: "pending";
4
7
  held: "held";
@@ -91,7 +94,7 @@ export declare const flowAssignmentTargetingContextSchema: z.ZodMiniObject<{
91
94
  }, z.core.$strip>;
92
95
  export declare const flowAssignmentRecipientRequestSchema: z.ZodMiniObject<{
93
96
  identities: z.ZodMiniDefault<z.ZodMiniArray<z.ZodMiniObject<{
94
- type: z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<"anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token", string>>;
97
+ type: z.ZodMiniUnion<readonly [z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<"anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token", string>>, z.ZodMiniType<`externalId.${string}`, `externalId.${string}`, z.core.$ZodTypeInternals<`externalId.${string}`, `externalId.${string}`>>]>;
95
98
  value: z.ZodMiniString<string>;
96
99
  }, z.core.$strip>>>;
97
100
  context: z.ZodMiniOptional<z.ZodMiniObject<{
@@ -236,7 +239,7 @@ export declare const listPendingFlowAssignmentsResponseSchema: z.ZodMiniObject<{
236
239
  }, z.core.$strip>;
237
240
  export declare const claimPendingFlowAssignmentsRequestSchema: z.ZodMiniObject<{
238
241
  identities: z.ZodMiniDefault<z.ZodMiniArray<z.ZodMiniObject<{
239
- type: z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<"anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token", string>>;
242
+ type: z.ZodMiniUnion<readonly [z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<"anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token", string>>, z.ZodMiniType<`externalId.${string}`, `externalId.${string}`, z.core.$ZodTypeInternals<`externalId.${string}`, `externalId.${string}`>>]>;
240
243
  value: z.ZodMiniString<string>;
241
244
  }, z.core.$strip>>>;
242
245
  context: z.ZodMiniOptional<z.ZodMiniObject<{
@@ -355,7 +358,7 @@ export declare const claimPendingFlowAssignmentsResponseSchema: z.ZodMiniObject<
355
358
  }, z.core.$strip>;
356
359
  export declare const updateFlowAssignmentLifecycleRequestSchema: z.ZodMiniObject<{
357
360
  identities: z.ZodMiniDefault<z.ZodMiniArray<z.ZodMiniObject<{
358
- type: z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<"anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token", string>>;
361
+ type: z.ZodMiniUnion<readonly [z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<"anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token", string>>, z.ZodMiniType<`externalId.${string}`, `externalId.${string}`, z.core.$ZodTypeInternals<`externalId.${string}`, `externalId.${string}`>>]>;
359
362
  value: z.ZodMiniString<string>;
360
363
  }, z.core.$strip>>>;
361
364
  context: z.ZodMiniOptional<z.ZodMiniObject<{
@@ -444,7 +447,7 @@ export declare const updateFlowAssignmentLifecycleRequestSchema: z.ZodMiniObject
444
447
  }, z.core.$strip>;
445
448
  export declare const releaseFlowAssignmentClaimRequestSchema: z.ZodMiniObject<{
446
449
  identities: z.ZodMiniDefault<z.ZodMiniArray<z.ZodMiniObject<{
447
- type: z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<"anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token", string>>;
450
+ type: z.ZodMiniUnion<readonly [z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<"anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token", string>>, z.ZodMiniType<`externalId.${string}`, `externalId.${string}`, z.core.$ZodTypeInternals<`externalId.${string}`, `externalId.${string}`>>]>;
448
451
  value: z.ZodMiniString<string>;
449
452
  }, z.core.$strip>>>;
450
453
  holdGroupToken: z.ZodMiniString<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"flow-assignments.d.ts","sourceRoot":"","sources":["../src/flow-assignments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAQ9B,eAAO,MAAM,0BAA0B;;;;;;;;;;EAUrC,CAAC;AAEH,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG/C,CAAC;AAEH,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAI/C,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBrC,CAAC;AAEH,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGnD,CAAC;AAEH,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMnD,CAAC;AAEH,eAAO,MAAM,yCAAyC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGpD,CAAC;AAEH,eAAO,MAAM,0CAA0C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOrD,CAAC;AAEH,eAAO,MAAM,uCAAuC;;;;;;;;iBAKlD,CAAC;AAEH,eAAO,MAAM,wCAAwC;;iBAEnD,CAAC;AAEH,eAAO,MAAM,2CAA2C;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAC7B,CAAC;AAC5B,eAAO,MAAM,mDAAmD;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAE/D,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC/E,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CACpD,OAAO,oCAAoC,CAC3C,CAAC;AACF,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CACpD,OAAO,oCAAoC,CAC3C,CAAC;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC/E,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CACxD,OAAO,wCAAwC,CAC/C,CAAC;AACF,MAAM,MAAM,mCAAmC,GAAG,CAAC,CAAC,MAAM,CACzD,OAAO,yCAAyC,CAChD,CAAC;AACF,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CACxD,OAAO,wCAAwC,CAC/C,CAAC;AACF,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,MAAM,CACvD,OAAO,uCAAuC,CAC9C,CAAC;AACF,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CACxD,OAAO,wCAAwC,CAC/C,CAAC;AACF,MAAM,MAAM,oCAAoC,GAAG,CAAC,CAAC,MAAM,CAC1D,OAAO,0CAA0C,CACjD,CAAC;AACF,MAAM,MAAM,qCAAqC,GAAG,CAAC,CAAC,MAAM,CAC3D,OAAO,2CAA2C,CAClD,CAAC"}
1
+ {"version":3,"file":"flow-assignments.d.ts","sourceRoot":"","sources":["../src/flow-assignments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,UAAU,CAAC;AAO9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,MAAM,MAAM,yCAAyC,GAAG,cAAc,MAAM,EAAE,CAAC;AAC/E,MAAM,MAAM,+BAA+B,GACxC,iBAAiB,GACjB,yCAAyC,CAAC;AAsB7C,eAAO,MAAM,0BAA0B;;;;;;;;;;EAUrC,CAAC;AAEH,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAG/C,CAAC;AAEH,eAAO,MAAM,oCAAoC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAI/C,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAmBrC,CAAC;AAEH,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGnD,CAAC;AAEH,eAAO,MAAM,wCAAwC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMnD,CAAC;AAEH,eAAO,MAAM,yCAAyC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGpD,CAAC;AAEH,eAAO,MAAM,0CAA0C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOrD,CAAC;AAEH,eAAO,MAAM,uCAAuC;;;;;;;;iBAKlD,CAAC;AAEH,eAAO,MAAM,wCAAwC;;iBAEnD,CAAC;AAEH,eAAO,MAAM,2CAA2C;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAC7B,CAAC;AAC5B,eAAO,MAAM,mDAAmD;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAE/D,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC/E,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CACpD,OAAO,oCAAoC,CAC3C,CAAC;AACF,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CACpD,OAAO,oCAAoC,CAC3C,CAAC;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC/E,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CACxD,OAAO,wCAAwC,CAC/C,CAAC;AACF,MAAM,MAAM,mCAAmC,GAAG,CAAC,CAAC,MAAM,CACzD,OAAO,yCAAyC,CAChD,CAAC;AACF,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CACxD,OAAO,wCAAwC,CAC/C,CAAC;AACF,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,MAAM,CACvD,OAAO,uCAAuC,CAC9C,CAAC;AACF,MAAM,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CACxD,OAAO,wCAAwC,CAC/C,CAAC;AACF,MAAM,MAAM,oCAAoC,GAAG,CAAC,CAAC,MAAM,CAC1D,OAAO,0CAA0C,CACjD,CAAC;AACF,MAAM,MAAM,qCAAqC,GAAG,CAAC,CAAC,MAAM,CAC3D,OAAO,2CAA2C,CAClD,CAAC"}
@@ -1,5 +1,15 @@
1
1
  import * as z from "zod/mini";
2
- import { appEventCapabilitySchema, appEventFlagSchema, appEventIdentitySchema, } from "./app-event.js";
2
+ import { appEventCapabilitySchema, appEventFlagSchema, appEventIdentityTypeSchema, } from "./app-event.js";
3
+ const flowAssignmentExternalIdIdentityTypeSchema = z.string().check(z.trim(), z.minLength(1), z.regex(/^externalId\.[a-z0-9][a-z0-9_.-]*$/, {
4
+ message: "External ID identity type must use externalId.<type> with a lowercase Segment external ID type.",
5
+ }));
6
+ const flowAssignmentIdentitySchema = z.object({
7
+ type: z.union([
8
+ appEventIdentityTypeSchema,
9
+ flowAssignmentExternalIdIdentityTypeSchema,
10
+ ]),
11
+ value: z.string().check(z.trim(), z.minLength(1)),
12
+ });
3
13
  export const flowAssignmentStatusSchema = z.enum([
4
14
  "pending",
5
15
  "held",
@@ -16,7 +26,7 @@ export const flowAssignmentTargetingContextSchema = z.object({
16
26
  capabilities: z.optional(z.array(appEventCapabilitySchema)),
17
27
  });
18
28
  export const flowAssignmentRecipientRequestSchema = z.object({
19
- identities: z._default(z.array(appEventIdentitySchema), []),
29
+ identities: z._default(z.array(flowAssignmentIdentitySchema), []),
20
30
  context: z.optional(flowAssignmentTargetingContextSchema),
21
31
  at: z.optional(z.number()),
22
32
  });
@@ -43,7 +53,7 @@ export const listPendingFlowAssignmentsResponseSchema = z.object({
43
53
  flowAssignments: z.array(flowAssignmentRecordSchema),
44
54
  });
45
55
  export const claimPendingFlowAssignmentsRequestSchema = z.object({
46
- identities: z._default(z.array(appEventIdentitySchema), []),
56
+ identities: z._default(z.array(flowAssignmentIdentitySchema), []),
47
57
  context: z.optional(flowAssignmentTargetingContextSchema),
48
58
  holdOwnerKey: z.string().check(z.trim(), z.minLength(1)),
49
59
  at: z.optional(z.number()),
@@ -54,7 +64,7 @@ export const claimPendingFlowAssignmentsResponseSchema = z.object({
54
64
  flowAssignments: z.array(flowAssignmentRecordSchema),
55
65
  });
56
66
  export const updateFlowAssignmentLifecycleRequestSchema = z.object({
57
- identities: z._default(z.array(appEventIdentitySchema), []),
67
+ identities: z._default(z.array(flowAssignmentIdentitySchema), []),
58
68
  context: z.optional(flowAssignmentTargetingContextSchema),
59
69
  flowAssignmentId: z.string().check(z.trim(), z.minLength(1)),
60
70
  flowVersionId: z.optional(z.string().check(z.trim(), z.minLength(1))),
@@ -62,7 +72,7 @@ export const updateFlowAssignmentLifecycleRequestSchema = z.object({
62
72
  at: z.optional(z.number()),
63
73
  });
64
74
  export const releaseFlowAssignmentClaimRequestSchema = z.object({
65
- identities: z._default(z.array(appEventIdentitySchema), []),
75
+ identities: z._default(z.array(flowAssignmentIdentitySchema), []),
66
76
  holdGroupToken: z.string().check(z.trim(), z.minLength(1)),
67
77
  holdOwnerKey: z.optional(z.string().check(z.trim(), z.minLength(1))),
68
78
  at: z.optional(z.number()),
@@ -27,9 +27,9 @@ export declare const HOST_EVENT_KEYS: {
27
27
  * Stable capability tokens announced by the browser SDK during init.
28
28
  * These are versioned and namespaced to support forward-compatible negotiation.
29
29
  */
30
- export declare const SDK_PROTOCOL_CAPABILITIES: readonly ["gx.protocol.public.v1", "gx.command.configure.v1", "gx.command.open.v1", "gx.command.prefetch.v1", "gx.command.prerender.v1", "gx.command.identify.v1", "gx.command.setContainer.v1", "gx.command.close.v1", "gx.command.reset.v1", "gx.command.setDefaultContainerPolicy.v1"];
30
+ export declare const SDK_PROTOCOL_CAPABILITIES: readonly ["gx.protocol.public.v1", "gx.command.configure.v1", "gx.command.open.v1", "gx.command.prefetch.v1", "gx.command.prerender.v1", "gx.command.identify.v1", "gx.command.setContainer.v1", "gx.command.close.v1", "gx.command.reset.v1", "gx.command.setDefaultContainerPolicy.v1", "gx.command.track.v1"];
31
31
  export type SdkProtocolCapability = (typeof SDK_PROTOCOL_CAPABILITIES)[number];
32
32
  export declare const LOADER_RUNTIME_GLOBAL_KEY: "__getuserfeedback_runtime";
33
- export declare const LOADER_RUNTIME_PROTOCOL_VERSION: "v1";
33
+ export declare const LOADER_RUNTIME_PROTOCOL_VERSION: "v2";
34
34
  export declare const toHostEventName: (key: string) => string;
35
35
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/host/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB;;;;;;CAMnB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAC7B,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAI1D,eAAO,MAAM,eAAe,EAAG,kBAA2B,CAAC;AAE3D,eAAO,MAAM,mBAAmB,EAAG,kBAA2B,CAAC;AAI/D,eAAO,MAAM,iBAAiB,EAAG,kBAA2B,CAAC;AAE7D,eAAO,MAAM,eAAe;;;;;;;;;;;;;CAalB,CAAC;AAgDX;;;GAGG;AACH,eAAO,MAAM,yBAAyB,2RAG5B,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;AAC9E,eAAO,MAAM,+BAA+B,EAAG,IAAa,CAAC;AAG7D,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,MACjB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/host/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB;;;;;;CAMnB,CAAC;AAEX,MAAM,MAAM,kBAAkB,GAC7B,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAI1D,eAAO,MAAM,eAAe,EAAG,kBAA2B,CAAC;AAE3D,eAAO,MAAM,mBAAmB,EAAG,kBAA2B,CAAC;AAI/D,eAAO,MAAM,iBAAiB,EAAG,kBAA2B,CAAC;AAE7D,eAAO,MAAM,eAAe;;;;;;;;;;;;;CAalB,CAAC;AAkDX;;;GAGG;AACH,eAAO,MAAM,yBAAyB,kTAG5B,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/E,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;AAC9E,eAAO,MAAM,+BAA+B,EAAG,IAAa,CAAC;AAG7D,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,KAAG,MACjB,CAAC"}
@@ -36,6 +36,7 @@ const SDK_COMMAND_CAPABILITY_BY_KIND = {
36
36
  close: "gx.command.close.v1",
37
37
  reset: "gx.command.reset.v1",
38
38
  setDefaultContainerPolicy: "gx.command.setDefaultContainerPolicy.v1",
39
+ track: "gx.command.track.v1",
39
40
  };
40
41
  const SDK_COMMAND_CAPABILITIES = [
41
42
  SDK_COMMAND_CAPABILITY_BY_KIND.configure,
@@ -47,6 +48,7 @@ const SDK_COMMAND_CAPABILITIES = [
47
48
  SDK_COMMAND_CAPABILITY_BY_KIND.close,
48
49
  SDK_COMMAND_CAPABILITY_BY_KIND.reset,
49
50
  SDK_COMMAND_CAPABILITY_BY_KIND.setDefaultContainerPolicy,
51
+ SDK_COMMAND_CAPABILITY_BY_KIND.track,
50
52
  ];
51
53
  /**
52
54
  * Stable capability tokens announced by the browser SDK during init.
@@ -57,6 +59,6 @@ export const SDK_PROTOCOL_CAPABILITIES = [
57
59
  ...SDK_COMMAND_CAPABILITIES,
58
60
  ];
59
61
  export const LOADER_RUNTIME_GLOBAL_KEY = "__getuserfeedback_runtime";
60
- export const LOADER_RUNTIME_PROTOCOL_VERSION = "v1";
62
+ export const LOADER_RUNTIME_PROTOCOL_VERSION = "v2";
61
63
  // Helper to construct full event name with prefix
62
64
  export const toHostEventName = (key) => `${HOST_EVENT_PREFIX}${key}`;
@@ -0,0 +1,10 @@
1
+ type ExternalIdArgumentCommandName = "identify" | "track";
2
+ type ExternalIdArgumentValueName = "traits" | "properties";
3
+ export declare const assertNoAmbiguousExternalIdsArgument: ({ argument, options, commandName, valueArgumentName, }: {
4
+ argument: unknown;
5
+ options: unknown;
6
+ commandName: ExternalIdArgumentCommandName;
7
+ valueArgumentName: ExternalIdArgumentValueName;
8
+ }) => void;
9
+ export {};
10
+ //# sourceMappingURL=external-id-argument-guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-id-argument-guards.d.ts","sourceRoot":"","sources":["../../src/host/external-id-argument-guards.ts"],"names":[],"mappings":"AAAA,KAAK,6BAA6B,GAAG,UAAU,GAAG,OAAO,CAAC;AAC1D,KAAK,2BAA2B,GAAG,QAAQ,GAAG,YAAY,CAAC;AAqC3D,eAAO,MAAM,oCAAoC,GAAI,wDAKlD;IACF,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,6BAA6B,CAAC;IAC3C,iBAAiB,EAAE,2BAA2B,CAAC;CAC/C,KAAG,IAQH,CAAC"}
@@ -0,0 +1,27 @@
1
+ const isAmbiguousExternalIdsArgument = (value) => {
2
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
3
+ return false;
4
+ }
5
+ const entries = Object.entries(value);
6
+ const externalIds = entries[0]?.[1];
7
+ return (entries.length === 1 &&
8
+ entries[0]?.[0] === "externalIds" &&
9
+ Array.isArray(externalIds) &&
10
+ externalIds.length > 0 &&
11
+ externalIds.every(isSegmentExternalIdLike));
12
+ };
13
+ const isSegmentExternalIdLike = (value) => {
14
+ if (value === null || typeof value !== "object" || Array.isArray(value)) {
15
+ return false;
16
+ }
17
+ return (typeof Reflect.get(value, "id") === "string" &&
18
+ typeof Reflect.get(value, "type") === "string" &&
19
+ Reflect.get(value, "collection") === "users" &&
20
+ Reflect.get(value, "encoding") === "none");
21
+ };
22
+ export const assertNoAmbiguousExternalIdsArgument = ({ argument, options, commandName, valueArgumentName, }) => {
23
+ if (options !== undefined || !isAmbiguousExternalIdsArgument(argument)) {
24
+ return;
25
+ }
26
+ throw new Error(`${commandName} received externalIds in the ${valueArgumentName} argument. Pass undefined for ${valueArgumentName} and provide externalIds as options instead.`);
27
+ };
@@ -5,6 +5,7 @@ export * from "./command-dispatch.js";
5
5
  export * from "./command-envelope.js";
6
6
  export * from "./command-settlement.js";
7
7
  export * from "./constants.js";
8
+ export * from "./external-id-argument-guards.js";
8
9
  export * from "./host-event-contract.js";
9
10
  export * from "./lazy-handle-client.js";
10
11
  export { createCommandRequestId } from "./request-id.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/host/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kCAAkC,CAAC;AACjD,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
@@ -5,6 +5,7 @@ export * from "./command-dispatch.js";
5
5
  export * from "./command-envelope.js";
6
6
  export * from "./command-settlement.js";
7
7
  export * from "./constants.js";
8
+ export * from "./external-id-argument-guards.js";
8
9
  export * from "./host-event-contract.js";
9
10
  export * from "./lazy-handle-client.js";
10
11
  export { createCommandRequestId } from "./request-id.js";
@@ -4,14 +4,32 @@
4
4
  * {@link FlowState} lives in `./host-event-contract` (re-exported from the `@getuserfeedback/protocol/host` barrel).
5
5
  */
6
6
  import type { Scope } from "../scopes.js";
7
- /** Supported identity kinds for analytics and tracking. */
7
+ /**
8
+ * Identifier types supported by event tracking and identity resolution.
9
+ *
10
+ * Business-specific identifiers are sent as Segment-compatible
11
+ * `context.externalIds` entries on app events or identify options.
12
+ *
13
+ * @see https://getuserfeedback.com/docs/guides/identity-resolution
14
+ */
8
15
  export type AppEventIdentityType = "anonymousId" | "userId" | "traits.email" | "traits.phone" | "context.device.id" | "context.device.advertisingId" | "context.device.token";
9
- /** A single identity (e.g. userId or anonymousId) and its value. */
16
+ /** A single standard identifier, such as a user ID, anonymous ID, email, or device ID. */
10
17
  export type AppEventIdentity = {
11
18
  type: AppEventIdentityType;
12
19
  value: string;
13
20
  };
14
- /** Page and device context you can attach to tracked events. */
21
+ /**
22
+ * Segment-compatible external identifier.
23
+ *
24
+ * Only `collection: "users"` participates in person identity resolution today.
25
+ */
26
+ export type AppEventExternalId = {
27
+ id: string;
28
+ type: string;
29
+ collection: "users";
30
+ encoding: "none";
31
+ };
32
+ /** Page, feature flag, and capability context attached to an event. */
15
33
  export type AppEventContext = {
16
34
  page?: {
17
35
  path?: string;
@@ -20,17 +38,27 @@ export type AppEventContext = {
20
38
  };
21
39
  locale?: string;
22
40
  userAgent?: string;
41
+ externalIds?: AppEventExternalId[] | undefined;
23
42
  flags?: AppEventFlag[] | undefined;
24
43
  capabilities?: AppEventCapability[] | undefined;
25
44
  };
45
+ /** Supported feature flag value shape. */
26
46
  export type AppEventFlagValue = string | number | boolean | null | AppEventFlagValue[] | {
27
47
  [key: string]: AppEventFlagValue;
28
48
  };
49
+ /**
50
+ * Supported event property value shape.
51
+ *
52
+ * @see https://getuserfeedback.com/docs/reference/events
53
+ */
54
+ export type AppEventJsonValue = AppEventFlagValue;
55
+ /** Feature flag provider metadata. */
29
56
  export type AppEventFlagProvider = {
30
57
  name: string;
31
58
  project?: string | undefined;
32
59
  environment?: string | undefined;
33
60
  };
61
+ /** Feature flag evaluation context attached to widget initialization or events. */
34
62
  export type AppEventFlag = {
35
63
  key: string;
36
64
  target?: string | undefined;
@@ -42,14 +70,17 @@ export type AppEventFlag = {
42
70
  reason?: string | undefined;
43
71
  evaluatedAt?: string | undefined;
44
72
  };
73
+ /** Host capability context attached to widget initialization or events. */
45
74
  export type AppEventCapability = {
46
75
  key: string;
47
76
  source?: string | undefined;
48
77
  provider?: AppEventFlagProvider | undefined;
49
78
  };
79
+ /** Feature flag evaluations accepted by SDK initialization. */
50
80
  export type FlagsInput = AppEventFlag[] | Record<string, AppEventFlagValue>;
81
+ /** Host capabilities accepted by SDK initialization. */
51
82
  export type CapabilitiesInput = Array<string | AppEventCapability>;
52
- /** Optional fields shared by all flow lifecycle events (traits, identities, context, timing). */
83
+ /** Optional fields shared by event payloads. */
53
84
  export type AppEventBase = {
54
85
  traits?: Record<string, unknown> | undefined;
55
86
  identities?: AppEventIdentity[] | undefined;
@@ -57,34 +88,46 @@ export type AppEventBase = {
57
88
  messageId?: string | undefined;
58
89
  timestamp?: number | undefined;
59
90
  };
60
- /** Reference to a specific survey/flow. */
91
+ /** Reference to a specific survey or flow. */
61
92
  export type AppEventSurveyReference = {
62
93
  surveyId: string;
63
94
  };
64
- /** Event payload when a flow is shown (Flow Viewed event). */
95
+ /** Event payload emitted when a flow is shown. */
65
96
  export type FlowViewedPayload = AppEventBase & {
97
+ origin?: "system" | undefined;
66
98
  event: "Flow Viewed";
67
99
  references: AppEventSurveyReference;
68
100
  };
69
- /** Event payload when a user dismisses a flow. */
101
+ /** Event payload emitted when a user dismisses a flow. */
70
102
  export type FlowDismissedPayload = AppEventBase & {
103
+ origin?: "system" | undefined;
71
104
  event: "Flow Dismissed";
72
105
  references: AppEventSurveyReference;
73
106
  };
74
107
  /**
75
- * Payload for {@link Client.track}. Use this to record when a flow is shown or dismissed.
76
- * Discriminate on the `event` field (`"Flow Viewed"` or `"Flow Dismissed"`).
108
+ * Event payload sent with `client.track()`.
109
+ *
110
+ * @see https://getuserfeedback.com/docs/reference/events
111
+ */
112
+ export type CustomerTrackPayload = AppEventBase & {
113
+ origin: "customer";
114
+ event: string;
115
+ properties?: Record<string, AppEventJsonValue> | undefined;
116
+ };
117
+ /**
118
+ * Event payload union. Use `origin` as the discriminator when handling the
119
+ * union directly.
77
120
  */
78
- export type AppEventPayload = FlowViewedPayload | FlowDismissedPayload;
79
- /** How the widget was loaded (e.g. via SDK, GTM, or a tag manager). */
121
+ export type AppEventPayload = FlowViewedPayload | FlowDismissedPayload | CustomerTrackPayload;
122
+ /** How the widget was loaded, such as SDK, GTM, Segment, or a custom loader. */
80
123
  export type ClientMetaLoader = "sdk" | "gtm" | "segment" | "rudderstack" | "tealium" | "custom";
81
- /** Delivery method for the widget script (e.g. ESM, script tag). */
124
+ /** Delivery method for the widget script. */
82
125
  export type ClientMetaTransport = "script-tag" | "esm" | "loader" | "tag-manager" | "snippet";
83
126
  /** Detected or configured front-end framework. */
84
127
  export type ClientMetaRuntimeFramework = "next" | "vite" | "webpack" | "plain";
85
128
  /** Runtime environment (browser or edge). */
86
129
  export type ClientMetaRuntimeEnv = "browser" | "edge";
87
- /** Metadata about the client and integration (e.g. loader, framework). Used for analytics and support. */
130
+ /** Metadata about the client integration, used for diagnostics and support. */
88
131
  export type ClientMeta = {
89
132
  loader: ClientMetaLoader;
90
133
  clientName?: string | undefined;
@@ -147,19 +190,23 @@ export type ConsentStatus = "pending" | "granted" | "denied" | "revoked";
147
190
  export type GrantScope = Scope;
148
191
  /** Consent configuration. Use a single decision for all scopes, or provide an explicit allow-list of granted scopes. */
149
192
  export type ConsentConfig = ConsentStatus | Scope[];
150
- /** Auth configuration (e.g. JWT for authenticated flows). */
193
+ /** Auth configuration, such as a JWT for authenticated flows. */
151
194
  export type AuthConfig = {
152
195
  jwt?: {
153
196
  token: string;
154
197
  } | null | undefined;
155
198
  };
156
- /** Options for {@link Client.configure}: color scheme, consent, and auth. */
199
+ /**
200
+ * Runtime configuration updates accepted by `client.configure()`.
201
+ *
202
+ * @see https://getuserfeedback.com/docs/security-and-privacy/compliance-and-consent
203
+ */
157
204
  export type ConfigureOptions = {
158
205
  colorScheme?: ColorSchemeConfig | undefined;
159
206
  consent?: ConsentConfig | undefined;
160
207
  auth?: AuthConfig | undefined;
161
208
  };
162
- /** @internal Options when initializing the widget: API key, color scheme, disableTelemetry, enableDebug, defaultConsent, capabilities, and optional customer targeting context. */
209
+ /** @internal Options when initializing the widget: API key, color scheme, disableTelemetry, enableDebug, defaultConsent, capabilities, and optional host targeting context. */
163
210
  export type InitOptions = {
164
211
  apiKey: string;
165
212
  colorScheme?: ColorSchemeConfig | undefined;
@@ -177,7 +224,8 @@ export type ClientOptions = {
177
224
  apiKey: string;
178
225
  /** Color scheme config: host-driven (loader observes attributes) or explicit. */
179
226
  colorScheme?: ColorSchemeConfig | undefined;
180
- /** Consent settings compatible with common privacy frameworks (GDPR, CCPA, LGPD) and CMP flows.
227
+ /**
228
+ * Initial consent state.
181
229
  *
182
230
  * Default: `granted` (all scopes).
183
231
  *
@@ -192,6 +240,8 @@ export type ClientOptions = {
192
240
  * Essential baseline scopes are always granted for core widget operation and cannot be denied:
193
241
  * - `functionality.storage`
194
242
  * - `security.storage`
243
+ *
244
+ * @see https://getuserfeedback.com/docs/security-and-privacy/compliance-and-consent
195
245
  */
196
246
  defaultConsent?: ConsentConfig | undefined;
197
247
  /** When true, prints debug logs to console. Narrow down with a namespace string/array eg. ```["loader", "handshake"]```. Default `false`.
@@ -211,9 +261,9 @@ export type ClientOptions = {
211
261
  * Excluded by default: user identity and detailed page fields (path/referrer/search).
212
262
  */
213
263
  disableTelemetry?: boolean | undefined;
214
- /** Customer feature flag evaluations collected with widget initialization. */
264
+ /** Feature flag evaluations collected with widget initialization. */
215
265
  flags?: FlagsInput | undefined;
216
- /** Customer host capabilities collected with widget initialization. */
266
+ /** Host capabilities collected with widget initialization. */
217
267
  capabilities?: CapabilitiesInput | undefined;
218
268
  _loaderUrl?: string | undefined;
219
269
  _coreUrl?: string | undefined;
@@ -253,20 +303,33 @@ export type PrerenderCommandPayload = {
253
303
  export type IdentifyTraitsOnlyCommandPayload = {
254
304
  kind: "identify";
255
305
  traits: Record<string, unknown>;
306
+ options?: IdentifyOptions | undefined;
256
307
  };
257
308
  /** Identify with userId and optional traits (`client.identify(userId, traits?)`). */
258
309
  export type IdentifyUserCommandPayload = {
259
310
  kind: "identify";
260
311
  userId: string;
261
312
  traits?: Record<string, unknown> | undefined;
313
+ options?: IdentifyOptions | undefined;
262
314
  };
263
315
  /** Identify command payload: either traits-only or userId+traits shape. */
264
316
  export type IdentifyCommandPayload = IdentifyTraitsOnlyCommandPayload | IdentifyUserCommandPayload;
265
- /** Track a flow shown or dismissed event. */
317
+ export type IdentifyOptions = {
318
+ externalIds?: AppEventExternalId[] | undefined;
319
+ };
320
+ export type TrackOptions = {
321
+ externalIds?: AppEventExternalId[] | undefined;
322
+ };
323
+ /**
324
+ * Command payload for `client.track()`.
325
+ *
326
+ * @see https://getuserfeedback.com/docs/reference/events
327
+ */
266
328
  export type TrackCommandPayload = AppEventBase & {
267
329
  kind: "track";
268
- event: "Flow Viewed" | "Flow Dismissed";
269
- references: AppEventSurveyReference;
330
+ origin: "customer";
331
+ event: string;
332
+ properties?: Record<string, AppEventJsonValue> | undefined;
270
333
  };
271
334
  /** Attach or detach a resolved flow handle from a host container. */
272
335
  export type SetContainerCommandPayload = {
@@ -306,8 +369,8 @@ export type CloseCommandPayload = {
306
369
  export type ResetCommandPayload = {
307
370
  kind: "reset";
308
371
  };
309
- /** Union of all widget action payloads (open, prefetch, identify, configure, etc.). */
310
- export type PublicCommandPayload = OpenCommandPayload | PrefetchCommandPayload | PrerenderCommandPayload | IdentifyCommandPayload | SetContainerCommandPayload | SetDefaultContainerPolicyCommandPayload | ConfigureCommandPayload | InitCommandPayload | CloseCommandPayload | ResetCommandPayload;
372
+ /** Union of widget action payloads such as open, prefetch, identify, configure, and track. */
373
+ export type PublicCommandPayload = OpenCommandPayload | PrefetchCommandPayload | PrerenderCommandPayload | IdentifyCommandPayload | SetContainerCommandPayload | SetDefaultContainerPolicyCommandPayload | ConfigureCommandPayload | InitCommandPayload | CloseCommandPayload | ResetCommandPayload | TrackCommandPayload;
311
374
  /** Input for a single widget action; same shape as {@link PublicCommandPayload}. */
312
375
  export type Command = PublicCommandPayload;
313
376
  /** Wrapper for a widget action (version, request id, idempotency key, optional client metadata, and the action payload). */
@@ -324,9 +387,11 @@ export type TelemetryIdentityType = AppEventIdentityType;
324
387
  /**
325
388
  * Event passed to the `beforeSend` hook in {@link Client.use}.
326
389
  * When `debug` is true, identities and full page context are included; when false, no identities and page is origin-only.
327
- * TODO(telemetry-contract-cleanup): Rename this SDK-facing type to
328
- * WidgetTelemetryEvent in a coordinated SDK-facing change so we can retire the
329
- * generic TelemetryEvent alias from shared telemetry.
390
+ *
391
+ * TODO(migration): Rename this SDK-facing type to WidgetTelemetryEvent in the
392
+ * same change that updates SDK imports, so the generic TelemetryEvent name can
393
+ * retire here without colliding with shared telemetry.
394
+ * [from=TelemetryEvent-widget-surface] [to=WidgetTelemetryEvent] [scope=slice] [priority=low]
330
395
  */
331
396
  export type TelemetryEvent = {
332
397
  type: string;