@usergist/sdk-core 0.1.0 → 0.1.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/segment-dsl.ts","../src/types/api.ts","../src/types/survey.ts","../src/types/inapp-message.ts","../src/types/request.ts","../src/types/targeting.ts","../src/types/themes.ts","../src/types/brand.ts","../src/types/integration.ts","../src/constants/push-events.ts","../src/types/push-runtime.ts","../src/evaluate/segment.ts","../src/evaluate/branch.ts","../src/evaluate/periodic.ts"],"names":["cutoff"],"mappings":"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","file":"mobile.cjs","sourcesContent":["// ==========================================================\n// Segment DSL (shared between server and SDK). The DSL is a\n// JSON structure — not raw SQL — so that:\n// 1. The dashboard UI can safely build/edit rules.\n// 2. The SDK can evaluate a lightweight subset client-side\n// for instant trigger firing (the server re-verifies).\n// 3. The server can compile the full DSL to ClickHouse SQL.\n// ==========================================================\n\nexport type ScalarValue = string | number | boolean\nexport type ScalarList = ReadonlyArray<string | number>\n\nexport type ComparisonOp =\n | 'eq'\n | 'neq'\n | 'in'\n | 'nin'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains'\n | 'starts_with'\n | 'exists'\n | 'not_exists'\n\nexport interface UserPropertyPredicate {\n readonly kind: 'user_property'\n readonly key: string\n readonly op: ComparisonOp\n readonly value?: ScalarValue | ScalarList\n}\n\nexport type CountOp = 'gte' | 'lte' | 'eq' | 'gt' | 'lt'\n\nexport interface EventCountPredicate {\n readonly kind: 'event_count'\n readonly eventName: string\n readonly op: CountOp\n readonly count: number\n readonly windowDays: number\n readonly propertyFilters?: ReadonlyArray<UserPropertyPredicate>\n}\n\nexport interface EventOccurredPredicate {\n readonly kind: 'event_occurred'\n readonly eventName: string\n readonly ever: boolean // true => \"has ever done X\", false => \"has never done X\"\n readonly windowDays?: number\n}\n\nexport type Predicate =\n | UserPropertyPredicate\n | EventCountPredicate\n | EventOccurredPredicate\n\nexport type Combinator = 'AND' | 'OR'\n\nexport interface PredicateGroup {\n readonly combinator: Combinator\n readonly predicates: ReadonlyArray<Predicate | PredicateGroup>\n}\n\nexport interface SegmentDsl {\n readonly version: 1\n readonly root: PredicateGroup\n}\n\nexport function emptySegmentDsl(): SegmentDsl {\n return { version: 1, root: { combinator: 'AND', predicates: [] } }\n}\n","export interface ApiError {\n readonly code: string\n readonly message: string\n readonly details?: unknown\n}\n\nexport interface ApiMeta {\n readonly total?: number\n readonly page?: number\n readonly limit?: number\n}\n\nexport interface ApiResponse<T> {\n readonly success: boolean\n readonly data?: T\n readonly error?: ApiError\n readonly meta?: ApiMeta\n}\n\nexport function ok<T>(data: T, meta?: ApiMeta): ApiResponse<T> {\n return meta ? { success: true, data, meta } : { success: true, data }\n}\n\nexport function err(\n code: string,\n message: string,\n details?: unknown,\n): ApiResponse<never> {\n return {\n success: false,\n error: details === undefined ? { code, message } : { code, message, details },\n }\n}\n","// ============================================================\n// Survey types — shared between API, dashboard, and SDKs.\n// A survey is a Campaign with type='survey'. The multi-step\n// question graph + branching lives here.\n// ============================================================\n\nimport type { PromptTheme, FrequencyCaps, SerializedSegmentRules } from './prompt.js'\nimport type { PushFrequencyCap, PushSchedule } from './campaign.js'\nimport type { AudienceSpec, TriggerSpec } from './targeting.js'\nimport type { ThemeMode } from './brand.js'\n\nexport type SurveyQuestionType =\n | 'single_choice'\n | 'multi_choice'\n | 'nps'\n | 'rating'\n | 'likert'\n | 'short_text'\n | 'long_text'\n | 'ranking'\n | 'single_date'\n | 'info_screen'\n\nexport type SurveyProgressStyle = 'bar' | 'dots' | 'none'\n\nexport interface SurveyChoiceOption {\n readonly id: string\n readonly label: string\n}\n\nexport interface SurveyTextValidation {\n readonly kind?: 'email' | 'url' | 'number' | 'regex'\n readonly pattern?: string\n readonly minLength?: number\n readonly maxLength?: number\n}\n\nexport interface BaseSurveyQuestion {\n readonly id: string\n readonly title: string\n readonly subtitle?: string\n readonly required?: boolean\n // Optional image rendered above the question title. Uploaded\n // through the dashboard composer; URL points at the public R2\n // bucket.\n readonly imageUrl?: string\n readonly mergeTagContext?: Readonly<Record<string, unknown>>\n}\n\nexport interface SingleChoiceQuestion extends BaseSurveyQuestion {\n readonly type: 'single_choice'\n readonly options: ReadonlyArray<SurveyChoiceOption>\n readonly allowOther?: boolean\n}\n\nexport interface MultiChoiceQuestion extends BaseSurveyQuestion {\n readonly type: 'multi_choice'\n readonly options: ReadonlyArray<SurveyChoiceOption>\n readonly minSelections?: number\n readonly maxSelections?: number\n readonly allowOther?: boolean\n}\n\nexport interface SurveyNpsQuestion extends BaseSurveyQuestion {\n readonly type: 'nps'\n readonly lowLabel?: string\n readonly highLabel?: string\n}\n\nexport interface SurveyRatingQuestion extends BaseSurveyQuestion {\n readonly type: 'rating'\n readonly scale: 5 | 10\n readonly style?: 'star' | 'numeric'\n readonly lowLabel?: string\n readonly highLabel?: string\n}\n\nexport interface LikertQuestion extends BaseSurveyQuestion {\n readonly type: 'likert'\n // 5-point: strongly disagree → strongly agree. Labels overridable.\n readonly labels?: readonly [string, string, string, string, string]\n}\n\nexport interface SurveyShortTextQuestion extends BaseSurveyQuestion {\n readonly type: 'short_text'\n readonly placeholder?: string\n readonly validation?: SurveyTextValidation\n}\n\nexport interface LongTextQuestion extends BaseSurveyQuestion {\n readonly type: 'long_text'\n readonly placeholder?: string\n readonly maxLength?: number\n}\n\nexport interface RankingQuestion extends BaseSurveyQuestion {\n readonly type: 'ranking'\n readonly items: ReadonlyArray<SurveyChoiceOption>\n}\n\nexport interface SingleDateQuestion extends BaseSurveyQuestion {\n readonly type: 'single_date'\n readonly minDate?: string\n readonly maxDate?: string\n}\n\nexport interface InfoScreenQuestion extends BaseSurveyQuestion {\n readonly type: 'info_screen'\n readonly body?: string\n}\n\nexport type SurveyQuestion =\n | SingleChoiceQuestion\n | MultiChoiceQuestion\n | SurveyNpsQuestion\n | SurveyRatingQuestion\n | LikertQuestion\n | SurveyShortTextQuestion\n | LongTextQuestion\n | RankingQuestion\n | SingleDateQuestion\n | InfoScreenQuestion\n\n// ---------- Branching DSL ----------\n\nexport type SurveyBranchOp =\n | 'eq'\n | 'neq'\n | 'lt'\n | 'lte'\n | 'gt'\n | 'gte'\n | 'includes'\n | 'not_includes'\n | 'answered'\n | 'unanswered'\n\nexport type SurveyBranchValue = string | number | boolean | ReadonlyArray<string | number>\n\nexport interface SurveyBranchCondition {\n readonly op: SurveyBranchOp\n readonly value?: SurveyBranchValue\n}\n\nexport interface SurveyBranch {\n readonly fromQuestionId: string\n readonly condition: SurveyBranchCondition\n readonly toQuestionId: string // or '__end__' to jump straight to end screen\n}\n\nexport const SURVEY_END_SENTINEL = '__end__'\n\n// ---------- End screen ----------\n\nexport type SurveyEndCtaKind = 'url' | 'deep_link' | 'close'\n\nexport interface SurveyEndCta {\n readonly kind: SurveyEndCtaKind\n readonly label: string\n readonly target?: string\n}\n\nexport interface SurveyFollowUp {\n readonly headline: string\n readonly body?: string\n readonly cta?: SurveyEndCta\n}\n\nexport interface SurveyEndScreen {\n readonly headline: string\n readonly body?: string\n readonly cta?: SurveyEndCta\n readonly followUp?: SurveyFollowUp\n}\n\n// ---------- Localization ----------\n\nexport interface SurveyLocalization {\n readonly defaultLanguage?: string\n readonly languages?: Readonly<Record<string, {\n readonly questions?: ReadonlyArray<SurveyQuestion>\n readonly endScreen?: SurveyEndScreen\n }>>\n}\n\n// ---------- Flow ----------\n\nexport interface SurveyFlow {\n readonly startQuestionId: string\n readonly questions: ReadonlyArray<SurveyQuestion>\n readonly branches: ReadonlyArray<SurveyBranch>\n readonly progressStyle: SurveyProgressStyle\n readonly backNavigation: boolean\n readonly localization?: SurveyLocalization\n readonly endScreen?: SurveyEndScreen\n}\n\n// ---------- Campaign surface ----------\n\nexport type SurveyDeliveryMode =\n | 'triggered'\n | 'scheduled'\n | 'on_demand'\n | 'link_only'\n\nexport type SurveyAttemptSource =\n | 'triggered'\n | 'scheduled'\n | 'link'\n | 'on_demand'\n | 'test'\n\nexport interface SurveyCampaign {\n readonly id: string\n readonly appId: string\n readonly name: string\n readonly type: 'survey'\n readonly mode: SurveyDeliveryMode\n readonly status: 'draft' | 'scheduled' | 'active' | 'paused' | 'completed' | 'archived'\n readonly audienceSegmentId: string | null\n readonly triggerEventName: string | null\n // Inline AudienceSpec + TriggerSpec mirroring prompts.audience/trigger.\n // Null until the dashboard / API write them; legacy\n // audienceSegmentId / triggerEventName remain authoritative until\n // both sides have migrated.\n readonly audience: AudienceSpec | null\n readonly trigger: TriggerSpec | null\n readonly schedule: PushSchedule | null\n readonly frequencyCap: PushFrequencyCap\n readonly cooldownSeconds: number | null\n readonly openAccess: boolean\n readonly saveResumeWindowSeconds: number\n readonly endScreen: SurveyEndScreen | null\n readonly themeMode: ThemeMode\n readonly theme: PromptTheme | null\n readonly startAt: string | null\n readonly endAt: string | null\n readonly startedAt: string | null\n readonly endedAt: string | null\n readonly createdAt: string\n readonly updatedAt: string\n}\n\nexport interface SurveyCampaignWithFlow extends SurveyCampaign {\n readonly flow: SurveyFlow\n}\n\n// ---------- Attempts / responses ----------\n\nexport interface SurveyAnswerRecord {\n readonly [questionId: string]: SurveyAnswerValue\n}\n\nexport type SurveyAnswerValue =\n | string\n | number\n | boolean\n | null\n | ReadonlyArray<string>\n | ReadonlyArray<number>\n\nexport interface SurveyAttempt {\n readonly id: string\n readonly campaignId: string\n readonly anonymousId: string\n readonly externalId: string | null\n readonly startedAt: string\n readonly completedAt: string | null\n readonly abandonedAt: string | null\n readonly currentQuestionId: string | null\n readonly progressSnapshot: SurveyAnswerRecord\n readonly source: SurveyAttemptSource\n readonly language: string | null\n}\n\nexport interface SurveyResponseRecord {\n readonly id: string\n readonly attemptId: string\n readonly campaignId: string\n readonly questionId: string\n readonly answerValue: SurveyAnswerValue\n readonly answeredAt: string\n}\n\n// ---------- SDK-facing payloads ----------\n\nexport interface SurveySummary {\n readonly id: string\n readonly name: string\n readonly mode: SurveyDeliveryMode\n readonly source: SurveyAttemptSource\n readonly offeredAt?: string\n readonly resumableAttemptId?: string | null\n}\n\nexport interface SurveyOfferInstruction {\n readonly type: 'survey.offer'\n readonly surveyId: string\n readonly name: string\n readonly mode: SurveyDeliveryMode\n readonly source: SurveyAttemptSource\n readonly emittedAt: string\n}\n\nexport interface CreateSurveyAttemptRequest {\n readonly anonymousId: string\n readonly externalId?: string | null\n readonly source: SurveyAttemptSource\n readonly language?: string\n readonly resume?: boolean\n readonly sdkVersion?: string\n readonly appVersion?: string\n readonly platform?: string\n}\n\nexport interface CreateSurveyAttemptResponse {\n readonly attemptId: string\n readonly startQuestionId: string\n readonly progressSnapshot: SurveyAnswerRecord\n readonly currentQuestionId: string | null\n readonly resumed: boolean\n}\n\nexport interface SubmitSurveyAnswersRequest {\n readonly answers: ReadonlyArray<{\n readonly questionId: string\n readonly value: SurveyAnswerValue\n }>\n readonly currentQuestionId?: string | null\n}\n\nexport interface UpdateSurveyAttemptProgressRequest {\n readonly currentQuestionId: string | null\n readonly progressSnapshot: SurveyAnswerRecord\n}\n\nexport interface CompleteSurveyAttemptRequest {\n readonly finalAnswers?: ReadonlyArray<{\n readonly questionId: string\n readonly value: SurveyAnswerValue\n }>\n readonly latencyMs?: number\n}\n\nexport interface ResolveSurveyLinkRequest {\n readonly token: string\n readonly anonymousId: string\n readonly externalId?: string | null\n}\n\nexport interface ResolveSurveyLinkResponse {\n readonly surveyId: string\n readonly name: string\n readonly consentRequired: boolean\n readonly openAccess: boolean\n}\n\nexport interface SurveyShareLinkResponse {\n readonly url: string\n readonly token: string\n readonly expiresAt: string | null\n}\n\n// ---------- Templates ----------\n\nexport interface SurveyTemplate {\n readonly id: string\n readonly slug: string\n readonly name: string\n readonly description: string | null\n readonly flow: SurveyFlow\n readonly recommendedTriggerEvent: string | null\n readonly recommendedMode: SurveyDeliveryMode | null\n readonly createdAt: string\n}\n\n// ---------- Create / update requests ----------\n\nexport interface CreateSurveyRequest {\n readonly name: string\n readonly mode: SurveyDeliveryMode\n readonly flow: SurveyFlow\n readonly audienceSegmentId?: string | null\n readonly triggerEventName?: string | null\n readonly schedule?: PushSchedule | null\n readonly frequencyCap?: PushFrequencyCap\n readonly frequency?: FrequencyCaps\n readonly cooldownSeconds?: number | null\n readonly openAccess?: boolean\n readonly saveResumeWindowSeconds?: number\n readonly endScreen?: SurveyEndScreen\n readonly themeMode?: ThemeMode\n readonly theme?: PromptTheme\n readonly startAt?: string | null\n readonly endAt?: string | null\n readonly status?: SurveyCampaign['status']\n}\n\nexport interface UpdateSurveyRequest extends Partial<CreateSurveyRequest> {\n readonly status?: SurveyCampaign['status']\n}\n\nexport interface CloneSurveyFromTemplateRequest {\n readonly name?: string\n readonly audienceSegmentId?: string | null\n readonly triggerEventName?: string | null\n}\n\n// ---------- Analytics ----------\n\nexport interface SurveyFunnelStep {\n readonly questionId: string\n readonly shown: number\n readonly answered: number\n readonly skipped: number\n}\n\nexport interface SurveyQuestionDistribution {\n readonly questionId: string\n readonly type: SurveyQuestionType\n readonly distribution: Readonly<Record<string, number>>\n readonly average?: number\n readonly npsScore?: number\n readonly sampleSize: number\n}\n\nexport interface SurveyAnalytics {\n readonly surveyId: string\n readonly totals: {\n readonly started: number\n readonly completed: number\n readonly abandoned: number\n readonly completionRate: number\n }\n readonly funnel: ReadonlyArray<SurveyFunnelStep>\n readonly perQuestion: ReadonlyArray<SurveyQuestionDistribution>\n readonly npsOverTime?: ReadonlyArray<{ day: string; score: number; samples: number }>\n readonly perLanguage?: Readonly<Record<string, number>>\n}\n\n// ---------- SDK-side armed surveys ----------\n//\n// Mirrors `ArmedTrigger` (feedback). Returned by\n// `GET /v1/sdk/armed-surveys` for every triggered + active survey\n// the SDK should evaluate locally on each `track()`. The full\n// `survey` payload is included so the SDK can render immediately\n// on a match without a follow-up content fetch.\n\nexport interface ArmedSurvey {\n readonly campaignId: string\n readonly eventName: string\n readonly segmentRules?: SerializedSegmentRules | null\n /** True only when the SDK can make the same targeting decision locally. */\n readonly clientSideEligible?: boolean\n readonly cooldownSeconds: number | null\n readonly frequencyCap: PushFrequencyCap\n readonly survey: SurveyCampaignWithFlow\n}\n","import type { AudienceSpec, TriggerSpec } from './targeting.js'\nimport type { ThemeMode } from './brand.js'\n\nexport const INAPP_SHOWN_EVENT_NAME = '$inapp_shown'\nexport const INAPP_DISMISSED_EVENT_NAME = '$inapp_dismissed'\nexport const INAPP_AUTO_DISMISSED_EVENT_NAME = '$inapp_auto_dismissed'\nexport const INAPP_CTA_CLICKED_EVENT_NAME = '$inapp_cta_clicked'\n\nexport type InAppMessageFormat = 'modal' | 'modal_full' | 'slideup'\n\nexport type InAppMessageStatus =\n | 'draft'\n | 'scheduled'\n | 'active'\n | 'paused'\n | 'completed'\n | 'archived'\n\nexport type InAppMessageMode = 'triggered' | 'scheduled'\n\nexport type JsonAction = Readonly<Record<string, unknown>>\n\nexport type InAppCtaAction =\n | 'open_url'\n | 'deep_link'\n | 'dismiss'\n | 'custom_event'\n | 'json'\n\nexport interface InAppCta {\n readonly label: string\n readonly action: InAppCtaAction\n readonly target?: string\n /** Host-defined action data dispatched to the app when this CTA is tapped. */\n readonly actionJson?: JsonAction\n}\n\n// Three-state cooldowns + cross-pillar caps. Each key is optional —\n// omitting means \"no cap on this dimension\".\nexport interface InAppFrequency {\n readonly cooldownAfterShownDays?: number\n readonly cooldownAfterDismissedDays?: number\n readonly cooldownAfterCtaClickedDays?: number\n readonly maxImpressionsPerUser?: number\n readonly perPillarDays?: number\n readonly perGlobalDays?: number\n}\n\nexport interface InAppMessage {\n readonly id: string\n readonly appId: string\n readonly name: string\n readonly status: InAppMessageStatus\n readonly mode: InAppMessageMode\n\n readonly audienceSegmentId: string | null\n readonly audience: AudienceSpec | null\n readonly trigger: TriggerSpec | null\n readonly triggerEventName: string | null\n readonly schedule: unknown | null\n\n readonly screenAllowlist: ReadonlyArray<string>\n readonly screenDenylist: ReadonlyArray<string>\n\n readonly frequency: InAppFrequency\n\n readonly conversionGoalEvent: string | null\n readonly conversionWindowHours: number\n\n readonly priority: number\n readonly forceShow: boolean\n readonly autoDismissSeconds: number | null\n\n readonly format: InAppMessageFormat\n readonly title: string\n readonly body: string | null\n readonly imageUrl: string | null\n readonly themeMode: ThemeMode\n readonly backgroundColor: string | null\n readonly accentColor: string | null\n readonly backdropEnabled: boolean\n readonly ctas: ReadonlyArray<InAppCta>\n\n readonly startAt: string | null\n readonly endAt: string | null\n readonly createdAt: string\n readonly updatedAt: string\n}\n\nexport interface CreateInAppMessageRequest {\n readonly name: string\n readonly audienceSegmentId?: string | null\n readonly audience?: AudienceSpec\n readonly trigger?: TriggerSpec\n readonly triggerEventName?: string | null\n readonly screenAllowlist?: ReadonlyArray<string>\n readonly screenDenylist?: ReadonlyArray<string>\n readonly frequency?: InAppFrequency\n readonly conversionGoalEvent?: string | null\n readonly conversionWindowHours?: number\n readonly priority?: number\n readonly forceShow?: boolean\n readonly autoDismissSeconds?: number | null\n readonly format: InAppMessageFormat\n readonly title: string\n readonly body?: string | null\n readonly imageUrl?: string | null\n readonly themeMode?: ThemeMode\n readonly backgroundColor?: string | null\n readonly accentColor?: string | null\n readonly backdropEnabled?: boolean\n readonly ctas?: ReadonlyArray<InAppCta>\n readonly startAt?: string | null\n readonly endAt?: string | null\n readonly status?: InAppMessageStatus\n}\n\nexport interface UpdateInAppMessageRequest extends Partial<CreateInAppMessageRequest> {\n readonly status?: InAppMessageStatus\n}\n\nexport interface InAppMessageAnalytics {\n readonly totals: {\n readonly impressions: number\n readonly dismissed: number\n readonly autoDismissed: number\n readonly ctaClicked: number\n }\n readonly timeline: ReadonlyArray<{\n readonly day: string\n readonly impressions: number\n readonly dismissed: number\n readonly ctaClicked: number\n }>\n}\n\n// Subset of the message the SDK needs at render time. Mirrors\n// `ArmedTrigger.prompt` for feedback prompts — strips fields the device\n// doesn't need (audit columns, segment id) and leaves what the renderer\n// uses.\nexport interface ArmedInAppMessage {\n readonly messageId: string\n readonly eventName: string\n /** True only when the SDK can make the same targeting decision locally. */\n readonly clientSideEligible?: boolean\n readonly format: InAppMessageFormat\n readonly title: string\n readonly body: string | null\n readonly imageUrl: string | null\n readonly themeMode?: ThemeMode\n readonly backgroundColor: string | null\n readonly accentColor: string | null\n /** Defaults to true when omitted by an older API/cache payload. */\n readonly backdropEnabled?: boolean\n readonly ctas: ReadonlyArray<InAppCta>\n readonly autoDismissSeconds: number | null\n readonly screenAllowlist: ReadonlyArray<string>\n readonly screenDenylist: ReadonlyArray<string>\n readonly forceShow: boolean\n}\n","// ============================================================\n// Feature requests (5th pillar) — public types\n// ============================================================\n// Shared between API, dashboard, web-roadmap, and SDKs.\n// All shapes are `readonly`. Identity uses anonymousId + externalId\n// as on every other SDK payload — no new identity types here.\n\nimport type { ThemeMode } from './brand.js'\n\nexport type RequestStatus =\n | 'under_review'\n | 'planned'\n | 'in_progress'\n | 'shipped'\n | 'declined'\n\nexport type RequestFollowSource = 'upvote_auto' | 'manual'\n\nexport type RequestSort = 'top' | 'newest' | 'recently_updated'\n\nexport type RequestPersonalFilter = 'submitted' | 'upvoted' | 'following'\n\n// Event-name constants for the 7 events emitted by the request engine.\n// All flow through services/ingest.ts and become segmentable like every\n// other event (no segment-engine code changes needed).\nexport const REQUEST_SUBMITTED_EVENT_NAME = '$request_submitted' as const\nexport const REQUEST_UPVOTED_EVENT_NAME = '$request_upvoted' as const\nexport const REQUEST_UNUPVOTED_EVENT_NAME = '$request_unupvoted' as const\nexport const REQUEST_FOLLOWED_EVENT_NAME = '$request_followed' as const\nexport const REQUEST_UNFOLLOWED_EVENT_NAME = '$request_unfollowed' as const\nexport const REQUEST_STATUS_CHANGED_EVENT_NAME = '$request_status_changed' as const\nexport const REQUEST_RESPONDED_EVENT_NAME = '$request_responded' as const\nexport const REQUEST_COMMENTED_EVENT_NAME = '$request_commented' as const\nexport const REQUEST_COMMENT_EDITED_EVENT_NAME = '$request_comment_edited' as const\nexport const REQUEST_COMMENT_DELETED_EVENT_NAME = '$request_comment_deleted' as const\n\n// ---------- core domain shapes ----------\n\n/**\n * A feature request with viewer-relative state attached. Returned from\n * detail and list endpoints; `viewer*` fields are computed server-side\n * from the caller's identity.\n */\nexport interface Request {\n readonly id: string\n readonly appId: string\n readonly title: string\n readonly description: string\n readonly status: RequestStatus\n readonly devResponse: string | null\n readonly upvoteCount: number\n readonly followerCount: number\n readonly createdAt: string\n readonly updatedAt: string\n readonly statusChangedAt: string\n readonly lastRespondedAt: string | null\n readonly viewerHasUpvoted: boolean\n readonly viewerIsFollowing: boolean\n readonly viewerIsSubmitter: boolean\n}\n\n/** Compact summary used in list views and search typeahead. */\nexport interface RequestSummary {\n readonly id: string\n readonly title: string\n readonly description: string\n readonly status: RequestStatus\n readonly upvoteCount: number\n readonly followerCount: number\n readonly createdAt: string\n readonly statusChangedAt: string\n readonly viewerHasUpvoted: boolean\n readonly viewerIsFollowing: boolean\n}\n\n/** Search-as-you-type result; the SDK shows up to 5. */\nexport interface RequestSearchResult {\n readonly id: string\n readonly title: string\n readonly status: RequestStatus\n readonly upvoteCount: number\n}\n\n// ---------- toggle return shapes ----------\n\n/** Returned from POST/DELETE /v1/sdk/requests/:id/votes. */\nexport interface RequestVote {\n readonly requestId: string\n readonly upvoted: boolean\n readonly followed: boolean\n readonly upvoteCount: number\n readonly followerCount: number\n}\n\n/** Returned from POST/DELETE /v1/sdk/requests/:id/follows. */\nexport interface RequestFollow {\n readonly requestId: string\n readonly following: boolean\n readonly followerCount: number\n readonly source: RequestFollowSource\n}\n\n// ---------- request payloads ----------\n\nexport interface GetRequestsOptions {\n readonly sort?: RequestSort\n readonly statuses?: ReadonlyArray<RequestStatus>\n readonly mine?: RequestPersonalFilter\n readonly q?: string\n readonly cursor?: string | null\n readonly limit?: number\n}\n\nexport interface GetRequestsResult {\n readonly items: ReadonlyArray<RequestSummary>\n readonly nextCursor: string | null\n}\n\nexport interface SubmitRequestPayload {\n readonly anonymousId: string\n readonly externalId?: string | null\n readonly title: string\n readonly description: string\n}\n\nexport interface RequestVotePayload {\n readonly anonymousId: string\n readonly externalId?: string | null\n}\n\nexport interface RequestFollowPayload {\n readonly anonymousId: string\n readonly externalId?: string | null\n}\n\n// ---------- dashboard shapes ----------\n\nexport interface RequestDetail extends Request {\n readonly submitterAnonymousId: string\n readonly submitterExternalId: string | null\n readonly hidden: boolean\n}\n\nexport interface RequestUpvoterSegmentBreakdown {\n readonly requestId: string\n readonly totalUpvoters: number\n readonly segments: ReadonlyArray<{\n readonly segmentId: string\n readonly segmentName: string\n readonly count: number\n readonly percentage: number\n }>\n}\n\nexport type RequestTimelineEntryKind =\n | 'submitted'\n | 'upvote_burst'\n | 'follow_burst'\n | 'status_changed'\n | 'responded'\n\nexport interface RequestTimelineEntry {\n readonly kind: RequestTimelineEntryKind\n readonly at: string\n readonly count?: number\n readonly fromStatus?: RequestStatus\n readonly toStatus?: RequestStatus\n readonly responseExcerpt?: string\n}\n\nexport interface RequestAnalytics {\n readonly submissions: ReadonlyArray<{ readonly date: string; readonly count: number }>\n readonly upvotes: ReadonlyArray<{ readonly date: string; readonly count: number }>\n readonly follows: ReadonlyArray<{ readonly date: string; readonly count: number }>\n readonly statusDistribution: Record<RequestStatus, number>\n readonly devResponseRate: number\n readonly medianResponseHours: number | null\n readonly leaderboard: ReadonlyArray<{\n readonly anonymousId: string\n readonly externalId: string | null\n readonly submissions: number\n readonly upvotes: number\n }>\n}\n\nexport interface UpdateRequestStatusRequest {\n readonly status: RequestStatus\n readonly responseAppend?: string\n}\n\nexport interface UpdateRequestResponseRequest {\n readonly body: string\n}\n\nexport interface UpdateRequestModerationRequest {\n readonly hidden: boolean\n}\n\nexport interface MergeRequestsRequest {\n readonly canonicalId: string\n readonly duplicateIds: ReadonlyArray<string>\n}\n\nexport interface BulkUpdateStatusRequest {\n readonly ids: ReadonlyArray<string>\n readonly status: RequestStatus\n}\n\nexport interface ListRequestsQuery {\n readonly sort?: RequestSort\n readonly status?: RequestStatus | ReadonlyArray<RequestStatus>\n readonly filter?: RequestPersonalFilter\n readonly anonymousId?: string\n readonly q?: string\n readonly hidden?: boolean\n readonly page?: number\n readonly limit?: number\n}\n\n// ---------- settings ----------\n\nexport interface RequestBranding {\n readonly logoUrl?: string | null\n readonly accentColor?: string | null\n readonly coverImageUrl?: string | null\n readonly introCopy?: string | null\n}\n\nexport interface RequestNotificationRules {\n readonly transitions?: Record<string, boolean>\n readonly responseFirst?: boolean\n readonly responseEdit?: boolean\n readonly templateOverrides?: {\n readonly statusChange?: string\n readonly response?: string\n }\n}\n\nexport interface RequestSettings {\n readonly appId: string\n readonly enabled: boolean\n readonly entryLabel: string\n readonly viewSegmentId: string | null\n readonly submitSegmentId: string | null\n readonly publicRoadmapEnabled: boolean\n readonly publicSlug: string | null\n readonly themeMode: ThemeMode\n readonly branding: RequestBranding\n readonly notificationRules: RequestNotificationRules\n}\n\nexport interface UpdateRequestSettingsRequest {\n readonly enabled?: boolean\n readonly entryLabel?: string\n readonly viewSegmentId?: string | null\n readonly submitSegmentId?: string | null\n readonly publicRoadmapEnabled?: boolean\n readonly publicSlug?: string | null\n readonly themeMode?: ThemeMode\n readonly branding?: RequestBranding\n readonly notificationRules?: RequestNotificationRules\n}\n\n// ---------- public web roadmap shapes ----------\n\n/** Public-safe request summary (no submitter identity). */\nexport interface RequestPublicSummary {\n readonly id: string\n readonly title: string\n readonly description: string\n readonly status: RequestStatus\n readonly upvoteCount: number\n readonly followerCount: number\n readonly createdAt: string\n readonly statusChangedAt: string\n}\n\nexport interface RequestPublicDetail extends RequestPublicSummary {\n readonly devResponse: string | null\n readonly lastRespondedAt: string | null\n}\n\nexport interface RequestPublicBranding {\n readonly entryLabel: string\n readonly appName: string\n readonly branding: RequestBranding\n readonly fallbackInstallUrl: string | null\n}\n\n// ---------- SDK push payload ----------\n\n/** Carried inside push/in-app message payloads when status changes. */\nexport interface RequestStatusChangedNotice {\n readonly requestId: string\n readonly title: string\n readonly oldStatus: RequestStatus\n readonly newStatus: RequestStatus\n readonly devResponseExcerpt?: string\n readonly receivedVia: 'push' | 'inapp'\n}\n\n// ---------- comments ----------\n\nexport interface RequestComment {\n readonly id: string\n readonly requestId: string\n readonly body: string\n readonly authorAnonymousId: string\n readonly authorExternalId: string | null\n readonly viewerIsAuthor: boolean\n readonly createdAt: string\n readonly updatedAt: string\n}\n\nexport interface PostCommentPayload {\n readonly anonymousId: string\n readonly externalId?: string | null\n readonly body: string\n}\n\nexport interface EditCommentPayload {\n readonly anonymousId: string\n readonly body: string\n}\n\n/** Host-app callbacks registered via `setRequestsHandlers`. */\nexport interface RequestsHandlers {\n readonly onSubmit?: (request: Request) => void\n readonly onVote?: (vote: RequestVote) => void\n readonly onFollow?: (follow: RequestFollow) => void\n readonly onStatusChanged?: (notice: RequestStatusChangedNotice) => void\n}\n","// ==========================================================\n// Inline targeting spec — used by feedback prompts, surveys,\n// and push campaigns. Wraps each pillar record with an\n// `AudienceSpec` (who) + `TriggerSpec` (when).\n//\n// One condition kind in `AudienceCondition` is `segment`,\n// which references saved Segments by id (so the dashboard\n// suggests existing segments in that one branch). All other\n// kinds are evaluated inline against user properties or\n// recent event aggregates.\n//\n// `TriggerSpec` is a discriminated union with a shared base\n// (`app_open`, `event`, `audience_join`). Pillar packages\n// add extra kinds locally (e.g. push adds `manual` /\n// `scheduled`) — engines `switch` on `kind` and treat\n// unknowns as no-op.\n// ==========================================================\n\nimport type { ComparisonOp } from './segment-dsl.js'\n\nexport type Platform = 'ios' | 'android' | 'web'\n\nexport type AudienceCombinator = 'all' | 'any'\n\nexport type AudienceMode = 'everyone' | 'match'\n\n// -------------------- Audience conditions ----------------\n\nexport interface SegmentCondition {\n readonly kind: 'segment'\n readonly op: 'is' | 'is_not'\n readonly segmentIds: ReadonlyArray<string>\n}\n\nexport interface CountryCondition {\n readonly kind: 'country'\n readonly op: 'is_any_of' | 'is_none_of'\n readonly values: ReadonlyArray<string> // ISO 3166-1 alpha-2\n}\n\nexport interface LastActiveCondition {\n readonly kind: 'last_active'\n readonly op: 'within_days' | 'before_days' | 'never'\n readonly days?: number\n}\n\nexport interface InstallDateCondition {\n readonly kind: 'install_date'\n // `*_days` operators are relative to today; `*_date` and `between`\n // pin to user-picked calendar dates (ISO yyyy-mm-dd).\n readonly op:\n | 'within_days'\n | 'before_days'\n | 'after_date'\n | 'before_date'\n | 'between'\n readonly days?: number\n readonly date?: string // ISO date — used by after_date / before_date\n readonly from?: string // ISO date — used by between\n readonly to?: string // ISO date — used by between\n}\n\nexport interface PlatformCondition {\n readonly kind: 'platform'\n readonly op: 'is' | 'is_not'\n readonly values: ReadonlyArray<Platform>\n}\n\nexport interface UserPropertyCondition {\n readonly kind: 'user_property'\n readonly key: string\n readonly op: ComparisonOp\n readonly value?: string | number | boolean | ReadonlyArray<string | number>\n}\n\nexport interface EventPropertyFilter {\n readonly key: string\n readonly op: ComparisonOp\n readonly value?: string | number | boolean | ReadonlyArray<string | number>\n}\n\nexport interface EventPerformedCondition {\n readonly kind: 'event_performed'\n readonly op: 'did' | 'did_not'\n readonly eventName: string\n /** @deprecated Kept so previously saved audience definitions still load. */\n readonly property?: EventPropertyFilter\n readonly propertyFilters?: ReadonlyArray<EventPropertyFilter>\n readonly windowDays?: number\n readonly minCount?: number\n}\n\nexport interface AppVersionCondition {\n readonly kind: 'app_version'\n // String comparison for v1 — \"2.10.0\" sorts before \"2.9.0\" lexically.\n // Acceptable until we ship a semver-aware compare; the dashboard\n // input warns users.\n readonly op: 'eq' | 'neq' | 'gte' | 'lte' | 'gt' | 'lt'\n readonly version: string\n}\n\nexport type AudienceCondition =\n | SegmentCondition\n | CountryCondition\n | LastActiveCondition\n | InstallDateCondition\n | PlatformCondition\n | UserPropertyCondition\n | EventPerformedCondition\n | AppVersionCondition\n\nexport type AudienceConditionKind = AudienceCondition['kind']\n\nexport interface AudienceSpec {\n readonly version: 1\n readonly mode: AudienceMode\n readonly combinator: AudienceCombinator\n readonly conditions: ReadonlyArray<AudienceCondition>\n}\n\nexport function emptyAudienceSpec(): AudienceSpec {\n return { version: 1, mode: 'everyone', combinator: 'all', conditions: [] }\n}\n\n// -------------------- Trigger spec -----------------------\n\nexport type TriggerOccurrenceMode = 'every' | 'after_nth' | 'first_only'\n\nexport interface TriggerOccurrence {\n readonly mode: TriggerOccurrenceMode\n readonly n?: number // required when mode === 'after_nth'\n}\n\nexport interface ActiveWindow {\n readonly startAt?: string // ISO datetime\n readonly endAt?: string // ISO datetime\n}\n\nexport interface AppOpenTrigger {\n readonly kind: 'app_open'\n readonly delaySeconds?: number\n readonly onceOnly?: boolean\n readonly activeWindow?: ActiveWindow\n}\n\nexport interface EventTrigger {\n readonly kind: 'event'\n readonly eventName: string\n readonly propertyFilters?: ReadonlyArray<EventPropertyFilter>\n readonly occurrence?: TriggerOccurrence\n readonly delaySeconds?: number\n readonly onceOnly?: boolean\n readonly activeWindow?: ActiveWindow\n}\n\nexport interface AudienceJoinTrigger {\n readonly kind: 'audience_join'\n readonly delaySeconds?: number\n readonly onceOnly?: boolean\n readonly activeWindow?: ActiveWindow\n}\n\nexport interface AppVersionChangedTrigger {\n readonly kind: 'app_version_changed'\n readonly delaySeconds?: number\n readonly onceOnly?: boolean\n readonly activeWindow?: ActiveWindow\n}\n\nexport type TriggerSpec =\n | AppOpenTrigger\n | EventTrigger\n | AudienceJoinTrigger\n | AppVersionChangedTrigger\n\nexport type TriggerKind = TriggerSpec['kind']\n\n/**\n * Synthetic event name the SDK emits whenever the host app cold-starts\n * or transitions from background to foreground. The trigger engine\n * indexes `app_open`-kind prompts under this name so the same matching\n * pipeline handles both event-driven and lifecycle-driven prompts.\n */\nexport const APP_OPEN_EVENT_NAME = '$app_open'\n\n/**\n * Synthetic event the engine indexes `audience_join` campaigns under.\n * Mirrors APP_OPEN_EVENT_NAME so the same matching pipeline handles\n * both lifecycle and audience-membership triggers.\n */\nexport const AUDIENCE_JOIN_EVENT_NAME = '$audience_join'\n\nexport const AUDIENCE_JOIN_TRIGGER_KIND: AudienceJoinTrigger['kind'] = 'audience_join'\n\n/**\n * Synthetic event the SDK emits on cold-start when the persisted app\n * version differs from the running binary's version. Lets in-app\n * messages (and feedback / surveys) target users right after an update\n * — e.g. \"What's new\" modals.\n */\nexport const APP_VERSION_CHANGED_EVENT_NAME = '$app_version_changed'\n\nexport function defaultTriggerSpec(): TriggerSpec {\n return { kind: 'app_open' }\n}\n\nexport function defaultEventTrigger(eventName = ''): EventTrigger {\n return {\n kind: 'event',\n eventName,\n occurrence: { mode: 'every' },\n }\n}\n","// ==========================================================\n// Preset themes for the Feedback Design step. 12 curated\n// presets + a custom-your-own option in the UI. Each preset\n// surfaces 3 swatches in the gallery card for quick scan.\n// ==========================================================\n\nexport interface ThemeColors {\n readonly primary: string\n readonly background: string\n readonly text: string\n readonly subtext: string\n readonly border: string\n readonly accent?: string\n readonly button?: string\n}\n\nexport type CornerRadiusPreset = 'sharp' | 'soft' | 'rounded' | 'pill'\n\nexport const RADIUS_PRESETS: Record<CornerRadiusPreset, number> = {\n sharp: 4,\n soft: 12,\n rounded: 20,\n pill: 999,\n}\n\nexport interface ThemePreset {\n readonly id: string\n readonly name: string\n readonly description: string\n readonly colors: ThemeColors\n readonly radius: number\n readonly fontFamily: string\n readonly swatches: readonly [string, string, string]\n}\n\n// Default font family for every preset. Matches the SDK's\n// DEFAULT_THEME so a freshly-saved theme renders the same in the\n// dashboard preview (web font loaded via next/font + Google Fonts\n// stylesheet) and on the mobile app (host bundles the .ttf via\n// react-native.config.js). Previously the presets used 'Inter',\n// which neither side had loaded — both fell back to system sans,\n// so designers saw a font drift between the dashboard and device.\nconst JAKARTA = 'Plus Jakarta Sans'\n\nexport const THEME_PRESETS: ReadonlyArray<ThemePreset> = [\n {\n id: 'minimal',\n name: 'Minimal',\n description: 'Clean neutral palette',\n colors: {\n primary: '#111827',\n background: '#FFFFFF',\n text: '#111827',\n subtext: '#6B7280',\n border: '#E5E7EB',\n button: '#111827',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#111827', '#FFFFFF', '#E5E7EB'],\n },\n {\n id: 'ocean',\n name: 'Ocean',\n description: 'Cool blue tones',\n colors: {\n primary: '#0EA5E9',\n background: '#F0F9FF',\n text: '#0C4A6E',\n subtext: '#0369A1',\n border: '#BAE6FD',\n button: '#0EA5E9',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#0EA5E9', '#0C4A6E', '#BAE6FD'],\n },\n {\n id: 'sunset',\n name: 'Sunset',\n description: 'Warm orange glow',\n colors: {\n primary: '#F97316',\n background: '#FFF7ED',\n text: '#7C2D12',\n subtext: '#C2410C',\n border: '#FED7AA',\n button: '#F97316',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#F97316', '#7C2D12', '#FED7AA'],\n },\n {\n id: 'forest',\n name: 'Forest',\n description: 'Natural green hues',\n colors: {\n primary: '#16A34A',\n background: '#F0FDF4',\n text: '#14532D',\n subtext: '#166534',\n border: '#BBF7D0',\n button: '#16A34A',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#16A34A', '#14532D', '#BBF7D0'],\n },\n {\n id: 'midnight',\n name: 'Midnight',\n description: 'Deep dark mode',\n colors: {\n primary: '#A78BFA',\n background: '#0F172A',\n text: '#F8FAFC',\n subtext: '#94A3B8',\n border: '#1E293B',\n button: '#A78BFA',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#A78BFA', '#0F172A', '#1E293B'],\n },\n {\n id: 'candy',\n name: 'Candy',\n description: 'Playful pink + violet',\n colors: {\n primary: '#EC4899',\n background: '#FDF2F8',\n text: '#831843',\n subtext: '#BE185D',\n border: '#FBCFE8',\n button: '#EC4899',\n },\n radius: 20,\n fontFamily: JAKARTA,\n swatches: ['#EC4899', '#831843', '#FBCFE8'],\n },\n {\n id: 'mono',\n name: 'Mono',\n description: 'High-contrast B&W',\n colors: {\n primary: '#000000',\n background: '#FFFFFF',\n text: '#000000',\n subtext: '#525252',\n border: '#000000',\n button: '#000000',\n },\n radius: 4,\n fontFamily: JAKARTA,\n swatches: ['#000000', '#FFFFFF', '#525252'],\n },\n {\n id: 'coral',\n name: 'Coral',\n description: 'Soft coral accent',\n colors: {\n primary: '#FB7185',\n background: '#FFF1F2',\n text: '#881337',\n subtext: '#9F1239',\n border: '#FECDD3',\n button: '#FB7185',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#FB7185', '#881337', '#FECDD3'],\n },\n {\n id: 'ink',\n name: 'Ink',\n description: 'Deep navy editorial',\n colors: {\n primary: '#1E3A8A',\n background: '#F8FAFC',\n text: '#0F172A',\n subtext: '#475569',\n border: '#CBD5E1',\n button: '#1E3A8A',\n },\n radius: 12,\n fontFamily: JAKARTA,\n swatches: ['#1E3A8A', '#0F172A', '#CBD5E1'],\n },\n {\n id: 'mint',\n name: 'Mint',\n description: 'Fresh teal vibe',\n colors: {\n primary: '#14B8A6',\n background: '#F0FDFA',\n text: '#134E4A',\n subtext: '#0F766E',\n border: '#99F6E4',\n button: '#14B8A6',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#14B8A6', '#134E4A', '#99F6E4'],\n },\n {\n id: 'slate',\n name: 'Slate',\n description: 'Quiet professional',\n colors: {\n primary: '#475569',\n background: '#F1F5F9',\n text: '#0F172A',\n subtext: '#64748B',\n border: '#CBD5E1',\n button: '#475569',\n },\n radius: 12,\n fontFamily: JAKARTA,\n swatches: ['#475569', '#0F172A', '#CBD5E1'],\n },\n {\n id: 'aurora',\n name: 'Aurora',\n description: 'Vibrant gradient pop',\n colors: {\n primary: '#8B5CF6',\n background: '#FAF5FF',\n text: '#3B0764',\n subtext: '#7E22CE',\n border: '#E9D5FF',\n accent: '#EC4899',\n button: '#8B5CF6',\n },\n radius: 20,\n fontFamily: JAKARTA,\n swatches: ['#8B5CF6', '#EC4899', '#E9D5FF'],\n },\n] as const\n\nexport function getThemePresetById(id: string): ThemePreset | undefined {\n return THEME_PRESETS.find((preset) => preset.id === id)\n}\n\nexport function defaultThemePreset(): ThemePreset {\n // The presets list is non-empty by construction; assert via index access.\n return THEME_PRESETS[0] as ThemePreset\n}\n","import type { PromptTheme } from './prompt.js'\nimport type { ThemePreset } from './themes.js'\n\nexport type BrandPillar = 'feedback' | 'survey' | 'inapp' | 'requests'\nexport type ThemeMode = 'app_default' | 'custom'\n\nexport interface BrandThemeTokens {\n readonly colors: {\n readonly primary: string\n readonly background: string\n readonly text: string\n readonly subtext: string\n readonly border: string\n }\n readonly radius: number\n readonly fontFamily: string\n}\n\nexport type BrandThemeRef = `preset:${string}` | `custom:${string}`\n\nexport interface BrandTheme {\n readonly ref: BrandThemeRef\n readonly id: string\n readonly kind: 'preset' | 'custom'\n readonly name: string\n readonly description?: string\n readonly tokens: BrandThemeTokens\n readonly swatches: readonly [string, string, string]\n readonly editable: boolean\n readonly assignedPillars: ReadonlyArray<BrandPillar>\n readonly createdAt?: string\n readonly updatedAt?: string\n}\n\nexport type BrandThemeDefaults = Readonly<Record<BrandPillar, BrandThemeRef>>\n\nexport interface AppBrandSettings {\n readonly appId: string\n readonly themes: ReadonlyArray<BrandTheme>\n readonly defaults: BrandThemeDefaults\n readonly resolvedDefaults: Readonly<Record<BrandPillar, BrandThemeTokens>>\n readonly updatedAt: string\n}\n\nexport interface CreateBrandThemeRequest {\n readonly name: string\n readonly tokens: BrandThemeTokens\n}\n\nexport interface UpdateBrandThemeRequest {\n readonly name?: string\n readonly tokens?: BrandThemeTokens\n}\n\nexport interface UpdateBrandThemeDefaultsRequest {\n readonly defaults: BrandThemeDefaults\n}\n\nexport function brandTokensFromPreset(\n preset: Pick<ThemePreset, 'colors' | 'radius' | 'fontFamily'>,\n): BrandThemeTokens {\n return {\n colors: {\n primary: preset.colors.primary,\n background: preset.colors.background,\n text: preset.colors.text,\n subtext: preset.colors.subtext,\n border: preset.colors.border,\n },\n radius: preset.radius,\n fontFamily: preset.fontFamily,\n }\n}\n\nexport function promptThemeFromBrandTokens(tokens: BrandThemeTokens): PromptTheme {\n return {\n colors: { ...tokens.colors },\n radius: tokens.radius,\n fontFamily: tokens.fontFamily,\n }\n}\n\nexport function inAppColorsFromBrandTokens(tokens: BrandThemeTokens): {\n readonly backgroundColor: string\n readonly accentColor: string\n} {\n return {\n backgroundColor: tokens.colors.background,\n accentColor: tokens.colors.primary,\n }\n}\n\nexport function requestAccentFromBrandTokens(tokens: BrandThemeTokens): string {\n return tokens.colors.primary\n}\n","import type { EventPropertyValue } from './event.js'\n\nexport const INTEGRATION_PROVIDERS = ['amplitude', 'mixpanel'] as const\nexport type IntegrationProvider = (typeof INTEGRATION_PROVIDERS)[number]\n\nexport const INTEGRATION_CATEGORIES = [\n 'feedback', 'surveys', 'inapp', 'push', 'requests', 'lifecycle',\n] as const\nexport type IntegrationCategory = (typeof INTEGRATION_CATEGORIES)[number]\n\nexport type IntegrationStatus = 'connected' | 'paused' | 'needs_attention' | 'disconnected'\nexport type AmplitudeIntegrationRegion = 'us' | 'eu'\nexport type MixpanelIntegrationRegion = 'us' | 'eu' | 'in'\nexport type IntegrationRegion = 'us' | 'eu' | 'in'\nexport type IntegrationDeliveryStatus =\n | 'pending' | 'leased' | 'retrying' | 'delivered' | 'dead_lettered' | 'skipped'\nexport type CoreEventSubjectRole = 'actor' | 'affected_user'\n\nexport interface CoreIntegrationEventDefinition {\n readonly key: string\n readonly name: string\n readonly category: IntegrationCategory | 'identity'\n readonly subjectRole: CoreEventSubjectRole\n readonly required?: boolean\n /** Stable output property key -> accepted source property aliases. */\n readonly properties: Readonly<Record<string, ReadonlyArray<string>>>\n}\n\nexport const USER_IDENTIFIED_EVENT_NAME = '$user_identified' as const\n\nfunction camelize(value: string): string {\n return value.replace(/_([a-z])/g, (_match, letter: string) => letter.toUpperCase())\n}\n\nconst ids = (...keys: string[]): Readonly<Record<string, ReadonlyArray<string>>> =>\n Object.fromEntries(keys.map((key) => [key, [key, camelize(key)]]))\n\nconst pushEvents: ReadonlyArray<readonly [string, string]> = [\n ['$push_sent', 'UserGist Push Sent'],\n ['$push_delivered', 'UserGist Push Delivered'],\n ['$push_received', 'UserGist Push Received'],\n ['$push_displayed', 'UserGist Push Displayed'],\n ['$push_opened', 'UserGist Push Opened'],\n ['$push_dismissed', 'UserGist Push Dismissed'],\n ['$push_clicked', 'UserGist Push Clicked'],\n ['$push_action_clicked', 'UserGist Push Action Clicked'],\n ['$push_bounced', 'UserGist Push Bounced'],\n]\n\nconst requestEvents: ReadonlyArray<readonly [string, string, CoreEventSubjectRole]> = [\n ['$request_submitted', 'UserGist Request Submitted', 'actor'],\n ['$request_upvoted', 'UserGist Request Upvoted', 'actor'],\n ['$request_unupvoted', 'UserGist Request Unupvoted', 'actor'],\n ['$request_followed', 'UserGist Request Followed', 'actor'],\n ['$request_unfollowed', 'UserGist Request Unfollowed', 'actor'],\n ['$request_status_changed', 'UserGist Request Status Changed', 'affected_user'],\n ['$request_responded', 'UserGist Request Responded', 'affected_user'],\n ['$request_commented', 'UserGist Request Commented', 'actor'],\n ['$request_comment_edited', 'UserGist Request Comment Edited', 'actor'],\n ['$request_comment_deleted', 'UserGist Request Comment Deleted', 'affected_user'],\n]\n\nconst answerProperties: Readonly<Record<string, ReadonlyArray<string>>> = {\n ...ids(\n 'question_id',\n 'question_type',\n 'question_title',\n 'answer_format',\n 'answer_present',\n 'answer_numeric_value',\n 'answer_selection_count',\n 'answer_text_length',\n ),\n // These aliases are generated only by the trusted server response paths.\n // The API delivery boundary removes them from public SDK events before this\n // normalizer runs. The complete answer_value stays in UserGist; destinations\n // receive a value only for server-verified structured data.\n answer_value: ['__usergist_destination_answer_value'],\n answer_display_value: ['__usergist_destination_answer_display_value'],\n}\n\nexport const CORE_INTEGRATION_EVENTS: ReadonlyArray<CoreIntegrationEventDefinition> = [\n { key: '$app_open', name: 'UserGist App Opened', category: 'lifecycle', subjectRole: 'actor', properties: {} },\n { key: '$app_version_changed', name: 'UserGist App Version Changed', category: 'lifecycle', subjectRole: 'actor', properties: { ...ids('old_version', 'new_version') } },\n { key: USER_IDENTIFIED_EVENT_NAME, name: 'UserGist User Identified', category: 'identity', subjectRole: 'actor', required: true, properties: {} },\n { key: '$feedback_prompt_shown', name: 'UserGist Feedback Prompt Shown', category: 'feedback', subjectRole: 'actor', properties: { ...ids('prompt_id') } },\n { key: '$feedback_response', name: 'UserGist Feedback Response Submitted', category: 'feedback', subjectRole: 'actor', properties: { ...ids('response_id', 'prompt_id', 'prompt_name', 'dismissed', 'latency_ms', 'answer_count', 'feedback_types') } },\n { key: '$feedback_answer_submitted', name: 'UserGist Feedback Answer Submitted', category: 'feedback', subjectRole: 'actor', properties: { ...ids('response_id', 'prompt_id', 'prompt_name'), ...answerProperties } },\n { key: '$survey_started', name: 'UserGist Survey Started', category: 'surveys', subjectRole: 'actor', properties: { ...ids('campaign_id', 'survey_name', 'attempt_id', 'language', 'source') } },\n { key: '$survey_answer_submitted', name: 'UserGist Survey Answer Submitted', category: 'surveys', subjectRole: 'actor', properties: { ...ids('response_id', 'campaign_id', 'survey_name', 'attempt_id', 'language'), ...answerProperties } },\n { key: '$survey_completed', name: 'UserGist Survey Completed', category: 'surveys', subjectRole: 'actor', properties: { ...ids('campaign_id', 'survey_name', 'attempt_id', 'language', 'source', 'duration_ms') } },\n { key: '$survey_abandoned', name: 'UserGist Survey Abandoned', category: 'surveys', subjectRole: 'actor', properties: { ...ids('campaign_id', 'survey_name', 'attempt_id', 'language', 'source', 'duration_ms') } },\n { key: '$inapp_shown', name: 'UserGist In-App Message Shown', category: 'inapp', subjectRole: 'actor', properties: { ...ids('message_id') } },\n { key: '$inapp_dismissed', name: 'UserGist In-App Message Dismissed', category: 'inapp', subjectRole: 'actor', properties: { ...ids('message_id', 'dismiss_reason') } },\n { key: '$inapp_auto_dismissed', name: 'UserGist In-App Message Auto-Dismissed', category: 'inapp', subjectRole: 'actor', properties: { ...ids('message_id', 'dismiss_reason') } },\n { key: '$inapp_cta_clicked', name: 'UserGist In-App Message CTA Clicked', category: 'inapp', subjectRole: 'actor', properties: { ...ids('message_id', 'cta_id', 'cta_index'), action: ['action', 'cta_action'] } },\n ...pushEvents.map(([key, name]) => ({\n key,\n name,\n category: 'push' as const,\n subjectRole: 'actor' as const,\n properties: {\n ...ids('delivery_id', 'campaign_id', 'delivery_state', 'failure_code'),\n action_id: ['action_id', 'actionId', 'action_button', 'actionButton'],\n },\n })),\n ...requestEvents.map(([key, name, subjectRole]) => ({ key, name, category: 'requests' as const, subjectRole, properties: { ...ids('request_id', 'comment_id', 'source', 'old_status', 'new_status', 'deleted_by'), usergist_actor_type: ['usergist_actor_type', 'actor_type'] } })),\n]\n\nconst CORE_EVENT_BY_KEY = new Map(CORE_INTEGRATION_EVENTS.map((event) => [event.key, event]))\n\nexport function getCoreIntegrationEvent(key: string): CoreIntegrationEventDefinition | null {\n return CORE_EVENT_BY_KEY.get(key) ?? null\n}\n\nexport function sanitizeCoreIntegrationProperties(\n definition: CoreIntegrationEventDefinition,\n input: Readonly<Record<string, unknown>> | null | undefined,\n): Readonly<Record<string, EventPropertyValue>> {\n if (!input) return {}\n const output: Record<string, EventPropertyValue> = {}\n for (const [outputKey, aliases] of Object.entries(definition.properties)) {\n const alias = aliases.find((candidate) => Object.prototype.hasOwnProperty.call(input, candidate))\n if (!alias) continue\n const value = input[alias]\n if (typeof value === 'string') output[outputKey] = value.slice(0, 1024)\n else if (typeof value === 'number' && Number.isFinite(value)) output[outputKey] = value\n else if (typeof value === 'boolean' || value === null) output[outputKey] = value\n }\n return output\n}\n\nexport interface IntegrationSummary {\n readonly id: string\n readonly provider: IntegrationProvider\n readonly status: IntegrationStatus\n readonly region: IntegrationRegion\n readonly categories: ReadonlyArray<IntegrationCategory>\n readonly credentialHint: string | null\n readonly connectedAt: string | null\n readonly pausedAt: string | null\n readonly lastVerifiedAt: string | null\n readonly lastSuccessAt: string | null\n readonly lastFailureAt: string | null\n readonly lastErrorCode: string | null\n readonly lastErrorMessage: string | null\n}\n\nexport type ConnectIntegrationRequest =\n | { readonly provider: 'amplitude'; readonly apiKey: string; readonly region: 'us' | 'eu'; readonly categories: ReadonlyArray<IntegrationCategory> }\n | { readonly provider: 'mixpanel'; readonly projectToken: string; readonly region: 'us' | 'eu' | 'in'; readonly categories: ReadonlyArray<IntegrationCategory>; readonly identityMode: 'simplified' }\n\nexport interface UpdateIntegrationRequest {\n readonly categories: ReadonlyArray<IntegrationCategory>\n}\n\nexport interface IntegrationTestResult {\n readonly accepted: true\n readonly eventName: 'UserGist Integration Connected'\n readonly deviceId: string\n readonly acceptedAt: string\n}\n\nexport interface IntegrationDeliverySummary {\n readonly id: string\n readonly eventKey: string\n readonly eventName: string\n readonly status: IntegrationDeliveryStatus\n readonly identity: { readonly anonymousId: string; readonly externalId: string | null }\n readonly occurredAt: string\n readonly attempts: number\n readonly providerStatusCode: number | null\n readonly lastErrorMessage: string | null\n}\n\nexport interface IntegrationDeliveriesResponse {\n readonly items: ReadonlyArray<IntegrationDeliverySummary>\n readonly nextCursor: string | null\n}\n","/**\n * Canonical event names emitted by the push pillar. These land in the\n * events pipeline so segments can query them like any other event.\n */\nexport const PUSH_EVENTS = {\n SENT: '$push_sent',\n DELIVERED: '$push_delivered',\n DISPLAYED: '$push_displayed',\n RECEIVED: '$push_received',\n OPENED: '$push_opened',\n DISMISSED: '$push_dismissed',\n CLICKED: '$push_clicked',\n ACTION_CLICKED: '$push_action_clicked',\n BOUNCED: '$push_bounced',\n SILENT_ACK: '$push_silent_ack',\n} as const\n\nexport type PushEventName = (typeof PUSH_EVENTS)[keyof typeof PUSH_EVENTS]\n","/**\n * Runtime types shared by the React Native, iOS, and Android SDKs for\n * the \"under the hood\" push primitives:\n * • Silent reachability ping payloads\n * • Delivery beacon contract (delivered / displayed / dismissed)\n * • Channel registry (Android NotificationChannel + iOS category)\n * • App-open beacon\n */\n\nexport interface SilentPushPayload {\n readonly usergist_silent: '1'\n readonly usergist_ping_id: string\n}\n\nexport type AndroidImportance = 0 | 1 | 2 | 3 | 4\n\nexport type ChannelCategory =\n | 'transactional'\n | 'marketing'\n | 'silent'\n | 'digest'\n | 'alert'\n\nexport interface PushChannelDef {\n readonly app_id: string\n readonly channel_id: string\n readonly display_name: string\n readonly description: string | null\n readonly importance: AndroidImportance\n readonly default_sound: string | null\n readonly default_vibrate: boolean\n readonly default_badge: boolean\n readonly category: ChannelCategory\n}\n\nexport interface DeliveryBeacon {\n readonly deliveryId: string\n readonly occurredAt?: string\n readonly attemptId?: string\n readonly actionButton?: string\n}\n\nexport type DeliveryBeaconKind =\n | 'delivered'\n | 'displayed'\n | 'dismissed'\n\nexport interface SilentAck {\n readonly pingId: string\n readonly anonymousId: string\n readonly receivedAt?: string\n}\n\nexport interface RebindRequest {\n readonly anonymousId: string\n readonly externalId: string\n readonly token: string\n}\n\nexport interface AppOpenBeacon {\n readonly anonymousId: string\n readonly occurredAt?: string\n}\n\n/**\n * SDK-side recognized payload after parsing a server-sent push. Both\n * APNs (via NSE) and FCM (via FirebaseMessagingService) decode into\n * this shape so the cross-platform UI/behaviour layer can stay\n * platform-agnostic.\n */\nexport interface ParsedPushPayload {\n readonly campaignId: string\n readonly variantId: string\n readonly deliveryId: string\n readonly title: string\n readonly body: string\n readonly imageUrl: string | null\n readonly deepLink: string | null\n readonly language: string | null\n readonly actionButtons: ReadonlyArray<{\n readonly label: string\n readonly action: 'open_app' | 'deep_link' | 'url' | 'dismiss'\n readonly target?: string\n }>\n readonly androidChannelId: string | null\n readonly silent: boolean\n readonly silentPingId: string | null\n}\n\n/**\n * Helper used by the data-only Android branch and the iOS NSE to\n * detect a silent reachability ping.\n */\nexport function isSilentPushPayload(\n raw: Record<string, unknown> | null | undefined,\n): boolean {\n if (!raw) return false\n return raw.usergist_silent === '1' && typeof raw.usergist_ping_id === 'string'\n}\n","import type {\n Predicate,\n PredicateGroup,\n SegmentDsl,\n UserPropertyPredicate,\n EventCountPredicate,\n EventOccurredPredicate,\n} from '../types/segment-dsl.js'\nimport type {\n SerializedSegmentRules,\n UserPropertyRule,\n} from '../types/prompt.js'\n\nexport interface UserState {\n readonly properties: Readonly<Record<string, string | number | boolean | null | undefined>>\n // eventCounts: eventName -> map of windowDays -> count\n readonly eventCounts: Readonly<Record<string, Readonly<Record<number, number>>>>\n // lastEventAt: eventName -> ISO timestamp (most recent)\n readonly lastEventAt: Readonly<Record<string, string | undefined>>\n}\n\n/**\n * Evaluate a segment DSL against a user snapshot.\n *\n * @param now - Reference timestamp (ms since epoch) used for time-window\n * predicates. MUST be supplied explicitly so evaluation is deterministic\n * across processes (server trigger engine + client SDK), independent of\n * wall-clock skew. Defaults to `Date.now()` for backwards compatibility,\n * but callers that care about parity should pass the same `now` they pass\n * to the matching server-side call.\n */\nexport function evaluateSegment(\n dsl: SegmentDsl,\n user: UserState,\n now: number = Date.now(),\n): boolean {\n return evaluateGroup(dsl.root, user, now)\n}\n\nfunction evaluateGroup(group: PredicateGroup, user: UserState, now: number): boolean {\n if (group.predicates.length === 0) return true\n if (group.combinator === 'AND') {\n return group.predicates.every((p) => evaluateNode(p, user, now))\n }\n return group.predicates.some((p) => evaluateNode(p, user, now))\n}\n\nfunction evaluateNode(node: Predicate | PredicateGroup, user: UserState, now: number): boolean {\n if ('combinator' in node) return evaluateGroup(node, user, now)\n switch (node.kind) {\n case 'user_property':\n return evaluateUserProperty(node, user)\n case 'event_count':\n return evaluateEventCount(node, user)\n case 'event_occurred':\n return evaluateEventOccurred(node, user, now)\n }\n}\n\nfunction evaluateUserProperty(p: UserPropertyPredicate, user: UserState): boolean {\n const actual = user.properties[p.key]\n switch (p.op) {\n case 'exists':\n return actual !== undefined && actual !== null\n case 'not_exists':\n return actual === undefined || actual === null\n case 'eq':\n return actual === p.value\n case 'neq':\n return actual !== p.value\n case 'in':\n return Array.isArray(p.value) && actual != null && (p.value as ReadonlyArray<unknown>).includes(actual)\n case 'nin':\n return Array.isArray(p.value) && actual != null && !(p.value as ReadonlyArray<unknown>).includes(actual)\n case 'gt':\n return typeof actual === 'number' && typeof p.value === 'number' && actual > p.value\n case 'gte':\n return typeof actual === 'number' && typeof p.value === 'number' && actual >= p.value\n case 'lt':\n return typeof actual === 'number' && typeof p.value === 'number' && actual < p.value\n case 'lte':\n return typeof actual === 'number' && typeof p.value === 'number' && actual <= p.value\n case 'contains':\n return typeof actual === 'string' && typeof p.value === 'string' && actual.includes(p.value)\n case 'starts_with':\n return typeof actual === 'string' && typeof p.value === 'string' && actual.startsWith(p.value)\n }\n}\n\nfunction evaluateEventCount(p: EventCountPredicate, user: UserState): boolean {\n const eventBucket = user.eventCounts[p.eventName]\n const count = eventBucket?.[p.windowDays] ?? 0\n switch (p.op) {\n case 'eq': return count === p.count\n case 'gte': return count >= p.count\n case 'lte': return count <= p.count\n case 'gt': return count > p.count\n case 'lt': return count < p.count\n }\n}\n\nfunction evaluateEventOccurred(p: EventOccurredPredicate, user: UserState, now: number): boolean {\n const last = user.lastEventAt[p.eventName]\n if (p.ever) {\n if (!last) return false\n if (p.windowDays == null) return true\n const cutoff = now - p.windowDays * 86400_000\n return Date.parse(last) >= cutoff\n }\n if (!last) return true\n if (p.windowDays == null) return false\n const cutoff = now - p.windowDays * 86400_000\n return Date.parse(last) < cutoff\n}\n\n// ============================================================\n// SerializedSegmentRules → SegmentDsl bridge.\n//\n// The SDK ships armed triggers with a flattened rule set\n// (`SerializedSegmentRules`) for transport efficiency. We deliberately keep\n// only ONE evaluator (`evaluateSegment`) so that server and SDK paths cannot\n// diverge. The bridge converts the serialized form into an AND-combined\n// PredicateGroup and delegates to the same engine.\n// ============================================================\n\nexport function evaluateSerializedSegmentRules(\n rules: SerializedSegmentRules | null | undefined,\n user: UserState,\n now: number = Date.now(),\n): boolean {\n if (!rules) return true\n const dsl = serializedRulesToDsl(rules)\n return evaluateSegment(dsl, user, now)\n}\n\nexport function serializedRulesToDsl(rules: SerializedSegmentRules): SegmentDsl {\n const predicates: Predicate[] = []\n\n for (const rule of rules.userProperties ?? []) {\n predicates.push(userPropertyRuleToPredicate(rule))\n }\n for (const rule of rules.eventCounts ?? []) {\n predicates.push({\n kind: 'event_count',\n eventName: rule.eventName,\n op: rule.op,\n count: rule.count,\n windowDays: rule.windowDays,\n })\n }\n\n return {\n version: 1,\n root: { combinator: 'AND', predicates },\n }\n}\n\nfunction userPropertyRuleToPredicate(rule: UserPropertyRule): UserPropertyPredicate {\n // SerializedSegmentRules constrains operators to a subset; cast safely.\n return {\n kind: 'user_property',\n key: rule.key,\n op: rule.op,\n value: rule.value as UserPropertyPredicate['value'],\n }\n}\n","// ============================================================\n// Branch DSL evaluator — shared by SDKs and dashboard preview.\n// Given a flow, a current question, and the answer just recorded,\n// returns the next question id (or SURVEY_END_SENTINEL).\n// ============================================================\n\nimport {\n SURVEY_END_SENTINEL,\n type SurveyAnswerRecord,\n type SurveyAnswerValue,\n type SurveyBranch,\n type SurveyBranchCondition,\n type SurveyFlow,\n type SurveyQuestion,\n} from '../types/survey.js'\n\nexport function evaluateBranchCondition(\n cond: SurveyBranchCondition,\n answer: SurveyAnswerValue | undefined,\n): boolean {\n if (cond.op === 'answered') return answer !== undefined && answer !== null && answer !== ''\n if (cond.op === 'unanswered') return answer === undefined || answer === null || answer === ''\n if (answer === undefined || answer === null) return false\n\n switch (cond.op) {\n case 'eq':\n return answer === cond.value\n case 'neq':\n return answer !== cond.value\n case 'lt':\n return typeof answer === 'number' && typeof cond.value === 'number' && answer < cond.value\n case 'lte':\n return typeof answer === 'number' && typeof cond.value === 'number' && answer <= cond.value\n case 'gt':\n return typeof answer === 'number' && typeof cond.value === 'number' && answer > cond.value\n case 'gte':\n return typeof answer === 'number' && typeof cond.value === 'number' && answer >= cond.value\n case 'includes':\n return Array.isArray(answer) && (answer as ReadonlyArray<unknown>).includes(cond.value as never)\n case 'not_includes':\n return Array.isArray(answer) && !(answer as ReadonlyArray<unknown>).includes(cond.value as never)\n default:\n return false\n }\n}\n\nexport function nextQuestionId(\n flow: SurveyFlow,\n currentQuestionId: string,\n answers: SurveyAnswerRecord,\n): string | null {\n const branches = flow.branches.filter((b) => b.fromQuestionId === currentQuestionId)\n const answer = answers[currentQuestionId]\n for (const branch of branches) {\n if (evaluateBranchCondition(branch.condition, answer)) {\n if (branch.toQuestionId === SURVEY_END_SENTINEL) return null\n return branch.toQuestionId\n }\n }\n return defaultNext(flow, currentQuestionId)\n}\n\nfunction defaultNext(flow: SurveyFlow, currentQuestionId: string): string | null {\n const idx = flow.questions.findIndex((q) => q.id === currentQuestionId)\n if (idx < 0 || idx >= flow.questions.length - 1) return null\n const next = flow.questions[idx + 1]\n return next ? next.id : null\n}\n\nexport function findQuestion(\n flow: SurveyFlow,\n questionId: string,\n): SurveyQuestion | undefined {\n return flow.questions.find((q) => q.id === questionId)\n}\n\nexport function findQuestionIndex(flow: SurveyFlow, questionId: string): number {\n return flow.questions.findIndex((q) => q.id === questionId)\n}\n\n// Conservative progress estimate: count the current index + 1 over total. Branching\n// makes an exact number impossible, so we expose the worst-case fraction.\nexport function estimateProgress(flow: SurveyFlow, currentQuestionId: string | null): number {\n if (!currentQuestionId) return 1\n const idx = findQuestionIndex(flow, currentQuestionId)\n if (idx < 0) return 0\n return (idx + 1) / Math.max(1, flow.questions.length)\n}\n\n// Given a branch filter list, compute the *reachable* set of questions from a starting\n// point. Used by the composer to render \"dead question\" warnings.\nexport function reachableQuestions(\n flow: SurveyFlow,\n startId?: string,\n): ReadonlySet<string> {\n const start = startId ?? flow.startQuestionId\n const visited = new Set<string>()\n const stack: string[] = [start]\n while (stack.length > 0) {\n const id = stack.pop()\n if (id === undefined) continue\n if (visited.has(id)) continue\n visited.add(id)\n const outgoing = flow.branches.filter((b) => b.fromQuestionId === id)\n for (const b of outgoing) {\n if (b.toQuestionId !== SURVEY_END_SENTINEL) stack.push(b.toQuestionId)\n }\n const idx = flow.questions.findIndex((q) => q.id === id)\n if (idx >= 0 && idx < flow.questions.length - 1) {\n const next = flow.questions[idx + 1]\n if (next) stack.push(next.id)\n }\n }\n return visited\n}\n","import type { PeriodicFrequency } from '../types/campaign.js'\n\nexport interface PeriodicSchedule {\n readonly frequency: PeriodicFrequency\n readonly hourLocal: number\n readonly minuteLocal: number\n /** 0..6 (Sun=0). Required for `weekly`. */\n readonly weekday?: number\n /** 1..31. Required for `monthly`. */\n readonly dayOfMonth?: number\n /** IANA timezone the hour/minute are expressed in. Defaults to UTC. */\n readonly tz?: string\n}\n\n/**\n * Returns the next firing instant (as a Date in UTC) for a structured\n * periodic schedule, strictly after `now`.\n *\n * Pure / dependency-free. Used both server-side (push-scheduler `isDue`\n * check) and client-side (dashboard \"Next occurrence\" preview). Keep\n * deterministic for a given (schedule, now) tuple — no randomness.\n *\n * The walk is bounded — daily 2 iters, weekly 8, monthly 13 — so DST\n * gaps and short-month overflows can't loop forever.\n */\nexport function nextPeriodicFire(\n schedule: PeriodicSchedule,\n now: Date = new Date(),\n): Date {\n const tz = schedule.tz || 'UTC'\n const start = startCandidate(schedule, now, tz)\n return walkForward(start, schedule, now, tz)\n}\n\n/**\n * Minutes east of UTC for `tz` at instant `at`. Falls back to 0 (UTC)\n * for invalid input. Exported so server-side callers can share the\n * same offset math the periodic walker uses (avoids a separate\n * implementation in push-scheduler.ts).\n */\nexport function tzOffsetMinutes(at: Date, tz: string): number {\n if (tz === 'UTC') return 0\n try {\n const fmt = getFormatter(tz)\n const parts = fmt.formatToParts(at).reduce<Record<string, string>>((acc, p) => {\n if (p.type !== 'literal') acc[p.type] = p.value\n return acc\n }, {})\n const utc = Date.UTC(\n Number(parts.year),\n Number(parts.month) - 1,\n Number(parts.day),\n Number(parts.hour) === 24 ? 0 : Number(parts.hour),\n Number(parts.minute),\n Number(parts.second),\n )\n return Math.round((utc - at.getTime()) / 60_000)\n } catch {\n return 0\n }\n}\n\nfunction startCandidate(\n schedule: PeriodicSchedule,\n now: Date,\n tz: string,\n): Date {\n const localNow = wallClock(now, tz)\n const target = new Date(localNow)\n target.setHours(schedule.hourLocal, schedule.minuteLocal, 0, 0)\n return localToUtc(target, tz)\n}\n\nfunction walkForward(\n candidate: Date,\n schedule: PeriodicSchedule,\n now: Date,\n tz: string,\n): Date {\n let cursor = candidate\n const max = schedule.frequency === 'daily' ? 2 : schedule.frequency === 'weekly' ? 8 : 13\n for (let i = 0; i < max; i++) {\n const local = wallClock(cursor, tz)\n if (matchesFrequency(local, schedule) && cursor.getTime() > now.getTime()) {\n return cursor\n }\n cursor = step(cursor, local, schedule, tz)\n }\n return cursor\n}\n\nfunction matchesFrequency(local: Date, schedule: PeriodicSchedule): boolean {\n if (schedule.frequency === 'daily') return true\n if (schedule.frequency === 'weekly') {\n return schedule.weekday === undefined || local.getDay() === schedule.weekday\n }\n return schedule.dayOfMonth === undefined || local.getDate() === schedule.dayOfMonth\n}\n\nfunction step(\n cursor: Date,\n cursorLocal: Date,\n schedule: PeriodicSchedule,\n tz: string,\n): Date {\n if (schedule.frequency === 'daily' || schedule.frequency === 'weekly') {\n return addDays(cursor, 1)\n }\n // Monthly: jump to the next month at the same dayOfMonth (or last day if shorter).\n const next = new Date(cursorLocal)\n next.setMonth(next.getMonth() + 1)\n if (schedule.dayOfMonth !== undefined) {\n const lastDay = lastDayOfMonth(next.getFullYear(), next.getMonth())\n next.setDate(Math.min(schedule.dayOfMonth, lastDay))\n }\n next.setHours(schedule.hourLocal, schedule.minuteLocal, 0, 0)\n return localToUtc(next, tz)\n}\n\nfunction addDays(d: Date, days: number): Date {\n const next = new Date(d.getTime())\n next.setDate(next.getDate() + days)\n return next\n}\n\nfunction lastDayOfMonth(year: number, monthIndex: number): number {\n return new Date(year, monthIndex + 1, 0).getDate()\n}\n\n/** Returns the Date adjusted so its `getX()` methods read in `tz`'s wall clock. */\nfunction wallClock(d: Date, tz: string): Date {\n const offsetMin = tzOffsetMinutes(d, tz)\n return new Date(d.getTime() + offsetMin * 60_000)\n}\n\n/** Inverse of `wallClock` — given a Date whose getX reads in `tz`, return UTC. */\nfunction localToUtc(localView: Date, tz: string): Date {\n const offsetMin = tzOffsetMinutes(localView, tz)\n return new Date(localView.getTime() - offsetMin * 60_000)\n}\n\n// `Intl.DateTimeFormat` construction dominates this module's cost (~100 µs\n// per ctor). The scheduler can call `nextPeriodicFire` thousands of times\n// per tick across many users, so we cache one formatter per tz at module\n// scope. Map is keyed by IANA name and lookups are O(1). Safe to share —\n// formatter instances are stateless across calls.\nconst FORMATTER_CACHE = /* @__PURE__ */ new Map<string, Intl.DateTimeFormat>()\n\nfunction getFormatter(tz: string): Intl.DateTimeFormat {\n const cached = FORMATTER_CACHE.get(tz)\n if (cached) return cached\n const fmt = new Intl.DateTimeFormat('en-US', {\n timeZone: tz,\n hour12: false,\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n })\n FORMATTER_CACHE.set(tz, fmt)\n return fmt\n}\n"]}
1
+ {"version":3,"sources":["../src/types/segment-dsl.ts","../src/types/api.ts","../src/types/workspace.ts","../src/types/survey.ts","../src/types/inapp-message.ts","../src/types/request.ts","../src/types/targeting.ts","../src/types/themes.ts","../src/types/brand.ts","../src/types/integration.ts","../src/constants/push-events.ts","../src/types/push-runtime.ts","../src/evaluate/segment.ts","../src/evaluate/branch.ts","../src/evaluate/periodic.ts","../src/types/web.ts","../src/personalization.ts","../src/presentation.ts"],"names":["id","key","cutoff","z","rendered"],"mappings":"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","file":"mobile.cjs","sourcesContent":["// ==========================================================\n// Segment DSL (shared between server and SDK). The DSL is a\n// JSON structure — not raw SQL — so that:\n// 1. The dashboard UI can safely build/edit rules.\n// 2. The SDK can evaluate a lightweight subset client-side\n// for instant trigger firing (the server re-verifies).\n// 3. The server can compile the full DSL to ClickHouse SQL.\n// ==========================================================\n\nexport type ScalarValue = string | number | boolean\nexport type ScalarList = ReadonlyArray<string | number>\n\nexport type ComparisonOp =\n | 'eq'\n | 'neq'\n | 'in'\n | 'nin'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'contains'\n | 'starts_with'\n | 'exists'\n | 'not_exists'\n\nexport interface UserPropertyPredicate {\n readonly kind: 'user_property'\n readonly key: string\n readonly op: ComparisonOp\n readonly value?: ScalarValue | ScalarList\n}\n\nexport type CountOp = 'gte' | 'lte' | 'eq' | 'gt' | 'lt'\n\nexport interface EventCountPredicate {\n readonly kind: 'event_count'\n readonly eventName: string\n readonly op: CountOp\n readonly count: number\n readonly windowDays: number\n readonly propertyFilters?: ReadonlyArray<UserPropertyPredicate>\n}\n\nexport interface EventOccurredPredicate {\n readonly kind: 'event_occurred'\n readonly eventName: string\n readonly ever: boolean // true => \"has ever done X\", false => \"has never done X\"\n readonly windowDays?: number\n}\n\nexport type Predicate =\n | UserPropertyPredicate\n | EventCountPredicate\n | EventOccurredPredicate\n\nexport type Combinator = 'AND' | 'OR'\n\nexport interface PredicateGroup {\n readonly combinator: Combinator\n readonly predicates: ReadonlyArray<Predicate | PredicateGroup>\n}\n\nexport interface SegmentDsl {\n readonly version: 1\n readonly root: PredicateGroup\n}\n\nexport function emptySegmentDsl(): SegmentDsl {\n return { version: 1, root: { combinator: 'AND', predicates: [] } }\n}\n","export interface ApiError {\n readonly code: string\n readonly message: string\n readonly details?: unknown\n}\n\nexport interface ApiMeta {\n readonly total?: number\n readonly page?: number\n readonly limit?: number\n}\n\nexport interface ApiResponse<T> {\n readonly success: boolean\n readonly data?: T\n readonly error?: ApiError\n readonly meta?: ApiMeta\n}\n\nexport function ok<T>(data: T, meta?: ApiMeta): ApiResponse<T> {\n return meta ? { success: true, data, meta } : { success: true, data }\n}\n\nexport function err(\n code: string,\n message: string,\n details?: unknown,\n): ApiResponse<never> {\n return {\n success: false,\n error: details === undefined ? { code, message } : { code, message, details },\n }\n}\n","export type WorkspaceRole = 'owner' | 'admin' | 'editor' | 'viewer'\n\nexport interface Workspace {\n readonly id: string\n readonly name: string\n readonly slug: string\n readonly region: string\n readonly timezone: string\n readonly createdAt: string\n readonly updatedAt: string\n}\n\n/** Workspace as returned from the authenticated `/v1/me` projection. */\nexport interface WorkspaceWithRole extends Workspace {\n readonly role: WorkspaceRole\n}\n\nexport interface WorkspaceMember {\n readonly workspaceId: string\n readonly userId: string\n readonly email: string\n readonly name?: string | null\n readonly role: WorkspaceRole\n readonly createdAt: string\n}\n\nexport interface WorkspaceInvite {\n readonly id: string\n readonly workspaceId: string\n readonly email: string\n readonly role: Exclude<WorkspaceRole, 'owner'>\n readonly deliveryStatus: 'pending' | 'sent' | 'failed'\n readonly expiresAt: string\n readonly createdAt: string\n}\n\nexport interface AcceptWorkspaceInviteRequest {\n readonly token: string\n}\n\nexport interface AcceptWorkspaceInviteResponse {\n readonly workspace: Workspace\n readonly role: WorkspaceRole\n readonly alreadyMember: boolean\n}\n\nexport interface User {\n readonly id: string\n readonly email: string\n readonly name?: string | null\n readonly emailVerifiedAt?: string | null\n readonly createdAt: string\n readonly onboardingCompletedAt: string | null\n // Cross-workspace operator flag. Set on a tiny number of internal\n // accounts; surfaced so the dashboard can render the /admin\n // surface. SDK consumers never see this — it's only populated by\n // /v1/me which write-keys can't call.\n readonly isSuperAdmin?: boolean\n}\n\nexport interface App {\n readonly setupMode?: 'sdk' | 'portal'\n readonly id: string\n readonly workspaceId: string\n readonly name: string\n readonly slug: string\n readonly platforms: ReadonlyArray<\n 'ios' | 'android' | 'react-native' | 'expo' | 'flutter' | 'web'\n >\n readonly webConfig?: import('./web.js').WebAppConfig\n readonly piiAllowList: ReadonlyArray<string>\n readonly lifecycleEventsEnabled: boolean\n readonly billingSuspendedAt: string | null\n readonly onboarding: AppOnboarding\n readonly createdAt: string\n readonly updatedAt: string\n}\n\nexport type OnboardingGoal =\n | 'feedback'\n | 'survey'\n | 'inapp'\n | 'push'\n | 'requests'\nexport type OnboardingStatus = 'in_progress' | 'deferred' | 'completed'\nexport type OnboardingStep =\n | 'connect'\n | 'verify'\n | 'experience'\n | 'push'\n | 'launch'\nexport type OnboardingPushChoice = 'pending' | 'configured' | 'skipped'\n\nexport interface AppOnboarding {\n readonly goal: OnboardingGoal | null\n readonly status: OnboardingStatus\n readonly step: OnboardingStep\n readonly pushChoice: OnboardingPushChoice\n readonly startedAt: string\n readonly deferredAt: string | null\n readonly completedAt: string | null\n}\n\nexport interface OnboardingEvent {\n readonly name: '$app_open'\n readonly occurredAt: string\n readonly receivedAt: string\n readonly anonymousId: string\n readonly externalId: string | null\n readonly identityType: 'anonymous' | 'identified'\n readonly platform: string | null\n readonly sdkVersion: string | null\n readonly appVersion: string | null\n}\n\nexport interface OnboardingFirstFeedback {\n readonly promptId: string\n readonly question: string\n readonly status: 'draft' | 'active' | 'paused' | 'archived'\n readonly createdAt: string\n readonly shownAt: string | null\n readonly responseAt: string | null\n readonly responseValue: number | string | ReadonlyArray<string> | null\n readonly responseAnonymousId: string | null\n readonly responseExternalId: string | null\n readonly lastDismissedAt: string | null\n}\n\n/** Small, ready-to-use first message; the full composer stays in the dashboard. */\nexport interface OnboardingInAppContent {\n readonly title: string\n readonly body: string\n readonly buttonLabel: string\n readonly format: 'modal' | 'slideup'\n}\n\nexport function defaultOnboardingMessage(appName: string): OnboardingInAppContent {\n return {\n title: `Welcome to ${appName.trim() || 'our app'}`,\n body: 'Glad you’re here. Take a look around and make yourself at home.',\n buttonLabel: 'Got it',\n format: 'modal',\n }\n}\n\nexport interface OnboardingFirstInApp extends Omit<OnboardingInAppContent, 'format'> {\n readonly format: 'modal' | 'modal_full' | 'slideup'\n readonly messageId: string\n readonly status: 'draft' | 'scheduled' | 'active' | 'paused' | 'completed' | 'archived'\n readonly shownAt: string | null\n readonly interactedAt: string | null\n readonly interaction: 'cta_clicked' | 'dismissed' | null\n readonly identityType: 'anonymous' | 'identified' | null\n}\n\nexport interface AppOnboardingStatus extends AppOnboarding {\n readonly clientKeyAuthenticatedAt: string | null\n readonly environment: WriteKey['environment']\n readonly firstEvent: OnboardingEvent | null\n readonly firstAudienceUserCreated: boolean\n readonly firstFeedback: OnboardingFirstFeedback | null\n readonly firstInApp?: OnboardingFirstInApp | null\n readonly pushCredentials: {\n readonly ios: boolean\n readonly android: boolean\n }\n}\n\nexport interface UpdateAppOnboardingRequest {\n readonly action?:\n | 'resume'\n | 'defer'\n | 'create_first_inapp'\n | 'first_inapp_completed'\n | 'create_first_feedback'\n | 'first_feedback_completed'\n | 'push_configured'\n | 'push_skipped'\n | 'complete'\n readonly step?: OnboardingStep\n readonly question?: string\n readonly message?: OnboardingInAppContent\n}\n\nexport interface DeferCurrentUserOnboardingRequest {\n readonly action: 'defer'\n}\n\nexport interface WriteKey {\n readonly id: string\n readonly appId: string\n readonly keyPrefix: string\n readonly environment: 'production' | 'staging' | 'development'\n readonly label?: string | null\n readonly revokedAt?: string | null\n readonly lastUsedAt?: string | null\n readonly createdAt: string\n}\n\nexport interface CreatedWriteKey extends WriteKey {\n readonly plaintext: string // only returned on creation\n}\n\nexport type ApiTokenScope =\n | 'sdk:subjects'\n | 'push.transactional'\n | 'users.properties.write'\n\n/**\n * Metadata for a workspace-scoped server credential. The plaintext secret is\n * deliberately absent and is only returned by the create endpoint.\n */\nexport interface ApiToken {\n readonly id: string\n readonly workspaceId: string\n readonly name: string\n readonly tokenPrefix: string\n readonly scopes: ReadonlyArray<ApiTokenScope>\n readonly expiresAt: string\n readonly revokedAt: string | null\n readonly lastUsedAt: string | null\n readonly createdAt: string\n}\n\nexport interface CreatedApiToken extends ApiToken {\n /** One-time server secret. Never ship this value inside a client app. */\n readonly plaintext: string\n}\n\nexport interface CreateApiTokenRequest {\n readonly name: string\n readonly scopes: ReadonlyArray<ApiTokenScope>\n readonly expiresInDays?: number\n}\n\n/** App plus its first environment-specific write key, returned atomically. */\nexport interface CreatedApp extends App {\n readonly writeKey: CreatedWriteKey\n}\n\n/**\n * Request body for `POST /v1/apps/:appId/write-keys/:keyId/rotate`. The grace\n * window is how long the old key keeps authenticating before the API starts\n * returning 401 — gives SDK consumers a deploy window before the cutover.\n */\nexport interface RotateWriteKeyRequest {\n readonly graceSeconds?: number\n}\n\n/**\n * Response from a successful key rotation. The new key's plaintext is\n * returned ONCE and never again — operators must capture it on rotation.\n */\nexport interface RotateWriteKeyResponse {\n readonly newKey: CreatedWriteKey\n readonly oldKey: WriteKey\n readonly oldKeyExpiresAt: string\n}\n","import type { PersonalizationSpec } from './personalization.js'\n// ============================================================\n// Survey types — shared between API, dashboard, and SDKs.\n// A survey is a Campaign with type='survey'. The multi-step\n// question graph + branching lives here.\n// ============================================================\n\nimport type {\n PromptTheme,\n FrequencyCaps,\n SerializedSegmentRules,\n} from './prompt.js'\nimport type { PushFrequencyCap, PushSchedule } from './campaign.js'\nimport type { AudienceSpec, TriggerSpec } from './targeting.js'\nimport type { ThemeMode } from './brand.js'\n\nexport type SurveyQuestionType =\n | 'single_choice'\n | 'multi_choice'\n | 'nps'\n | 'rating'\n | 'likert'\n | 'short_text'\n | 'long_text'\n | 'ranking'\n | 'single_date'\n | 'info_screen'\n\nexport type SurveyProgressStyle = 'bar' | 'dots' | 'none'\n\nexport interface SurveyChoiceOption {\n readonly id: string\n readonly label: string\n}\n\nexport interface SurveyTextValidation {\n readonly kind?: 'email' | 'url' | 'number' | 'regex'\n readonly pattern?: string\n readonly minLength?: number\n readonly maxLength?: number\n}\n\nexport interface BaseSurveyQuestion {\n readonly id: string\n readonly title: string\n readonly subtitle?: string\n readonly required?: boolean\n // Optional image rendered above the question title. Uploaded\n // through the dashboard composer; URL points at the public R2\n // bucket.\n readonly imageUrl?: string\n readonly mergeTagContext?: Readonly<Record<string, unknown>>\n}\n\nexport interface SingleChoiceQuestion extends BaseSurveyQuestion {\n readonly type: 'single_choice'\n readonly options: ReadonlyArray<SurveyChoiceOption>\n readonly allowOther?: boolean\n}\n\nexport interface MultiChoiceQuestion extends BaseSurveyQuestion {\n readonly type: 'multi_choice'\n readonly options: ReadonlyArray<SurveyChoiceOption>\n readonly minSelections?: number\n readonly maxSelections?: number\n readonly allowOther?: boolean\n}\n\nexport interface SurveyNpsQuestion extends BaseSurveyQuestion {\n readonly type: 'nps'\n readonly lowLabel?: string\n readonly highLabel?: string\n}\n\nexport interface SurveyRatingQuestion extends BaseSurveyQuestion {\n readonly type: 'rating'\n readonly scale: 5 | 10\n readonly style?: 'star' | 'numeric'\n readonly lowLabel?: string\n readonly highLabel?: string\n}\n\nexport interface LikertQuestion extends BaseSurveyQuestion {\n readonly type: 'likert'\n // 5-point: strongly disagree → strongly agree. Labels overridable.\n readonly labels?: readonly [string, string, string, string, string]\n}\n\nexport interface SurveyShortTextQuestion extends BaseSurveyQuestion {\n readonly type: 'short_text'\n readonly placeholder?: string\n readonly validation?: SurveyTextValidation\n}\n\nexport interface LongTextQuestion extends BaseSurveyQuestion {\n readonly type: 'long_text'\n readonly placeholder?: string\n readonly maxLength?: number\n}\n\nexport interface RankingQuestion extends BaseSurveyQuestion {\n readonly type: 'ranking'\n readonly items: ReadonlyArray<SurveyChoiceOption>\n}\n\nexport interface SingleDateQuestion extends BaseSurveyQuestion {\n readonly type: 'single_date'\n readonly minDate?: string\n readonly maxDate?: string\n}\n\nexport interface InfoScreenQuestion extends BaseSurveyQuestion {\n readonly type: 'info_screen'\n readonly body?: string\n}\n\nexport type SurveyQuestion =\n | SingleChoiceQuestion\n | MultiChoiceQuestion\n | SurveyNpsQuestion\n | SurveyRatingQuestion\n | LikertQuestion\n | SurveyShortTextQuestion\n | LongTextQuestion\n | RankingQuestion\n | SingleDateQuestion\n | InfoScreenQuestion\n\n// ---------- Branching DSL ----------\n\nexport type SurveyBranchOp =\n | 'eq'\n | 'neq'\n | 'lt'\n | 'lte'\n | 'gt'\n | 'gte'\n | 'includes'\n | 'not_includes'\n | 'answered'\n | 'unanswered'\n\nexport type SurveyBranchValue =\n | string\n | number\n | boolean\n | ReadonlyArray<string | number>\n\nexport interface SurveyBranchCondition {\n readonly op: SurveyBranchOp\n readonly value?: SurveyBranchValue\n}\n\nexport interface SurveyBranch {\n readonly fromQuestionId: string\n readonly condition: SurveyBranchCondition\n readonly toQuestionId: string // or '__end__' to jump straight to end screen\n}\n\nexport const SURVEY_END_SENTINEL = '__end__'\n\n// ---------- End screen ----------\n\nexport type SurveyEndCtaKind = 'url' | 'deep_link' | 'close'\n\nexport interface SurveyEndCta {\n readonly kind: SurveyEndCtaKind\n readonly label: string\n readonly target?: string\n}\n\nexport interface SurveyFollowUp {\n readonly headline: string\n readonly body?: string\n readonly cta?: SurveyEndCta\n}\n\nexport interface SurveyEndScreen {\n readonly headline: string\n readonly body?: string\n readonly cta?: SurveyEndCta\n readonly followUp?: SurveyFollowUp\n}\n\n// ---------- Localization ----------\n\nexport interface SurveyLocalization {\n readonly defaultLanguage?: string\n readonly languages?: Readonly<\n Record<\n string,\n {\n readonly questions?: ReadonlyArray<SurveyQuestion>\n readonly endScreen?: SurveyEndScreen\n }\n >\n >\n}\n\n// ---------- Flow ----------\n\nexport interface SurveyFlow {\n readonly personalization?: PersonalizationSpec | null\n readonly startQuestionId: string\n readonly questions: ReadonlyArray<SurveyQuestion>\n readonly branches: ReadonlyArray<SurveyBranch>\n readonly progressStyle: SurveyProgressStyle\n readonly backNavigation: boolean\n readonly localization?: SurveyLocalization\n readonly endScreen?: SurveyEndScreen\n}\n\n// ---------- Campaign surface ----------\n\nexport type SurveyDeliveryMode =\n | 'triggered'\n | 'scheduled'\n | 'on_demand'\n | 'link_only'\n\nexport type SurveyAttemptSource =\n | 'triggered'\n | 'scheduled'\n | 'link'\n | 'on_demand'\n | 'test'\n\nexport interface SurveyCampaign {\n readonly deliveryPlatforms?: ReadonlyArray<\n import('./web.js').DeliveryPlatform\n >\n readonly webPresentation?: import('./web.js').WebPresentation | null\n readonly id: string\n readonly appId: string\n readonly name: string\n readonly type: 'survey'\n readonly mode: SurveyDeliveryMode\n readonly status:\n | 'draft'\n | 'scheduled'\n | 'active'\n | 'paused'\n | 'completed'\n | 'archived'\n readonly audienceSegmentId: string | null\n readonly triggerEventName: string | null\n // Inline AudienceSpec + TriggerSpec mirroring prompts.audience/trigger.\n // Null until the dashboard / API write them; legacy\n // audienceSegmentId / triggerEventName remain authoritative until\n // both sides have migrated.\n readonly audience: AudienceSpec | null\n readonly trigger: TriggerSpec | null\n readonly schedule: PushSchedule | null\n readonly frequencyCap: PushFrequencyCap\n readonly cooldownSeconds: number | null\n readonly openAccess: boolean\n readonly saveResumeWindowSeconds: number\n readonly endScreen: SurveyEndScreen | null\n readonly themeMode: ThemeMode\n readonly theme: PromptTheme | null\n readonly startAt: string | null\n readonly endAt: string | null\n readonly startedAt: string | null\n readonly endedAt: string | null\n readonly createdAt: string\n readonly updatedAt: string\n}\n\nexport interface SurveyCampaignWithFlow extends SurveyCampaign {\n /** Server-authorized content snapshot; present only on an SDK response. */\n readonly presentationId?: string\n readonly flow: SurveyFlow\n}\n\n// ---------- Attempts / responses ----------\n\nexport interface SurveyAnswerRecord {\n readonly [questionId: string]: SurveyAnswerValue\n}\n\nexport type SurveyAnswerValue =\n | string\n | number\n | boolean\n | null\n | ReadonlyArray<string>\n | ReadonlyArray<number>\n\nexport interface SurveyAttempt {\n readonly id: string\n readonly campaignId: string\n readonly anonymousId: string\n readonly externalId: string | null\n readonly startedAt: string\n readonly completedAt: string | null\n readonly abandonedAt: string | null\n readonly currentQuestionId: string | null\n readonly progressSnapshot: SurveyAnswerRecord\n readonly source: SurveyAttemptSource\n readonly language: string | null\n}\n\nexport interface SurveyResponseRecord {\n readonly id: string\n readonly attemptId: string\n readonly campaignId: string\n readonly questionId: string\n readonly answerValue: SurveyAnswerValue\n readonly answeredAt: string\n}\n\n// ---------- SDK-facing payloads ----------\n\nexport interface SurveySummary {\n readonly id: string\n readonly name: string\n readonly mode: SurveyDeliveryMode\n readonly source: SurveyAttemptSource\n readonly offeredAt?: string\n readonly resumableAttemptId?: string | null\n}\n\nexport interface SurveyOfferInstruction {\n readonly type: 'survey.offer'\n readonly surveyId: string\n readonly name: string\n readonly mode: SurveyDeliveryMode\n readonly source: SurveyAttemptSource\n readonly emittedAt: string\n}\n\nexport interface CreateSurveyAttemptRequest {\n /** Stable ID for an explicitly new attempt; retained across offline retries. */\n readonly clientAttemptId?: string\n readonly localStart?: {\n readonly token: string\n readonly startedAt: string\n }\n readonly presentationId?: string\n readonly anonymousId: string\n readonly externalId?: string | null\n readonly source: SurveyAttemptSource\n readonly language?: string\n readonly resume?: boolean\n readonly sdkVersion?: string\n readonly appVersion?: string\n readonly platform?: string\n}\n\nexport interface CreateSurveyAttemptResponse {\n readonly resolvedContent?: SurveyCampaignWithFlow\n readonly attemptId: string\n readonly startQuestionId: string\n readonly progressSnapshot: SurveyAnswerRecord\n readonly currentQuestionId: string | null\n readonly resumed: boolean\n}\n\nexport interface SubmitSurveyAnswersRequest {\n readonly answers: ReadonlyArray<{\n readonly questionId: string\n readonly value: SurveyAnswerValue\n }>\n readonly currentQuestionId?: string | null\n}\n\nexport interface UpdateSurveyAttemptProgressRequest {\n readonly currentQuestionId: string | null\n readonly progressSnapshot: SurveyAnswerRecord\n}\n\nexport interface CompleteSurveyAttemptRequest {\n readonly finalAnswers?: ReadonlyArray<{\n readonly questionId: string\n readonly value: SurveyAnswerValue\n }>\n readonly latencyMs?: number\n}\n\nexport interface ResolveSurveyLinkRequest {\n readonly token: string\n readonly anonymousId: string\n readonly externalId?: string | null\n}\n\nexport interface ResolveSurveyLinkResponse {\n readonly surveyId: string\n readonly name: string\n readonly consentRequired: boolean\n readonly openAccess: boolean\n}\n\nexport interface SurveyShareLinkResponse {\n readonly url: string\n readonly token: string\n readonly expiresAt: string | null\n}\n\n// ---------- Templates ----------\n\nexport interface SurveyTemplate {\n readonly id: string\n readonly slug: string\n readonly name: string\n readonly description: string | null\n readonly flow: SurveyFlow\n readonly recommendedTriggerEvent: string | null\n readonly recommendedMode: SurveyDeliveryMode | null\n readonly createdAt: string\n}\n\n// ---------- Create / update requests ----------\n\nexport interface CreateSurveyRequest {\n readonly deliveryPlatforms?: ReadonlyArray<\n import('./web.js').DeliveryPlatform\n >\n readonly webPresentation?: import('./web.js').WebPresentation | null\n readonly name: string\n readonly mode: SurveyDeliveryMode\n readonly flow: SurveyFlow\n readonly audienceSegmentId?: string | null\n readonly triggerEventName?: string | null\n readonly schedule?: PushSchedule | null\n readonly frequencyCap?: PushFrequencyCap\n readonly frequency?: FrequencyCaps\n readonly cooldownSeconds?: number | null\n readonly openAccess?: boolean\n readonly saveResumeWindowSeconds?: number\n readonly endScreen?: SurveyEndScreen\n readonly themeMode?: ThemeMode\n readonly theme?: PromptTheme\n readonly startAt?: string | null\n readonly endAt?: string | null\n readonly status?: SurveyCampaign['status']\n}\n\nexport interface UpdateSurveyRequest extends Partial<CreateSurveyRequest> {\n readonly deliveryPlatforms?: ReadonlyArray<\n import('./web.js').DeliveryPlatform\n >\n readonly webPresentation?: import('./web.js').WebPresentation | null\n readonly status?: SurveyCampaign['status']\n}\n\nexport interface CloneSurveyFromTemplateRequest {\n readonly name?: string\n readonly audienceSegmentId?: string | null\n readonly triggerEventName?: string | null\n}\n\n// ---------- Analytics ----------\n\nexport interface SurveyFunnelStep {\n readonly questionId: string\n readonly shown: number\n readonly answered: number\n readonly skipped: number\n}\n\nexport interface SurveyQuestionDistribution {\n readonly questionId: string\n readonly type: SurveyQuestionType\n readonly distribution: Readonly<Record<string, number>>\n readonly average?: number\n readonly npsScore?: number\n readonly sampleSize: number\n}\n\nexport interface SurveyAnalytics {\n readonly surveyId: string\n readonly totals: {\n readonly started: number\n readonly completed: number\n readonly abandoned: number\n readonly completionRate: number\n }\n readonly funnel: ReadonlyArray<SurveyFunnelStep>\n readonly perQuestion: ReadonlyArray<SurveyQuestionDistribution>\n readonly npsOverTime?: ReadonlyArray<{\n day: string\n score: number\n samples: number\n }>\n readonly perLanguage?: Readonly<Record<string, number>>\n}\n\n// ---------- SDK-side armed surveys ----------\n//\n// Mirrors `ArmedTrigger` (feedback). Returned by\n// `GET /v1/sdk/armed-surveys` for every triggered + active survey\n// the SDK should evaluate locally on each `track()`. The full\n// `survey` payload is included so the SDK can render immediately\n// on a match without a follow-up content fetch.\n\nexport interface ArmedSurvey {\n /** Server-signed, non-personalized content for a safe local start. */\n readonly localStart?: {\n readonly token: string\n readonly expiresAt: string\n }\n readonly campaignId: string\n readonly eventName: string\n readonly segmentRules?: SerializedSegmentRules | null\n /** True only when the SDK can make the same targeting decision locally. */\n readonly clientSideEligible?: boolean\n readonly cooldownSeconds: number | null\n readonly frequencyCap: PushFrequencyCap\n readonly survey: SurveyCampaignWithFlow\n}\n","import type { PersonalizationSpec } from './personalization.js'\nimport type { AudienceSpec, TriggerSpec } from './targeting.js'\nimport type { ThemeMode } from './brand.js'\n\nexport const INAPP_SHOWN_EVENT_NAME = '$inapp_shown'\nexport const INAPP_DISMISSED_EVENT_NAME = '$inapp_dismissed'\nexport const INAPP_AUTO_DISMISSED_EVENT_NAME = '$inapp_auto_dismissed'\nexport const INAPP_CTA_CLICKED_EVENT_NAME = '$inapp_cta_clicked'\n\nexport type InAppMessageFormat = 'modal' | 'modal_full' | 'slideup'\n\nexport type InAppMessageStatus =\n | 'draft'\n | 'scheduled'\n | 'active'\n | 'paused'\n | 'completed'\n | 'archived'\n\nexport type InAppMessageMode = 'triggered' | 'scheduled'\n\nexport type JsonAction = Readonly<Record<string, unknown>>\n\nexport type InAppCtaAction =\n | 'open_url'\n | 'deep_link'\n | 'dismiss'\n | 'custom_event'\n | 'json'\n\nexport interface InAppCta {\n readonly label: string\n readonly action: InAppCtaAction\n readonly target?: string\n /** Host-defined action data dispatched to the app when this CTA is tapped. */\n readonly actionJson?: JsonAction\n}\n\n// Three-state cooldowns + cross-pillar caps. Each key is optional —\n// omitting means \"no cap on this dimension\".\nexport interface InAppFrequency {\n readonly cooldownAfterShownDays?: number\n readonly cooldownAfterDismissedDays?: number\n readonly cooldownAfterCtaClickedDays?: number\n readonly maxImpressionsPerUser?: number\n readonly perPillarDays?: number\n readonly perGlobalDays?: number\n}\n\nexport interface InAppMessage {\n readonly personalization?: PersonalizationSpec | null\n readonly deliveryPlatforms?: ReadonlyArray<\n import('./web.js').DeliveryPlatform\n >\n readonly webPresentation?: import('./web.js').WebPresentation | null\n readonly id: string\n readonly appId: string\n readonly name: string\n readonly status: InAppMessageStatus\n readonly mode: InAppMessageMode\n\n readonly audienceSegmentId: string | null\n readonly audience: AudienceSpec | null\n readonly trigger: TriggerSpec | null\n readonly triggerEventName: string | null\n readonly schedule: unknown | null\n\n readonly screenAllowlist: ReadonlyArray<string>\n readonly screenDenylist: ReadonlyArray<string>\n\n readonly frequency: InAppFrequency\n\n readonly conversionGoalEvent: string | null\n readonly conversionWindowHours: number\n\n readonly priority: number\n readonly forceShow: boolean\n readonly autoDismissSeconds: number | null\n\n readonly format: InAppMessageFormat\n readonly title: string\n readonly body: string | null\n readonly imageUrl: string | null\n readonly themeMode: ThemeMode\n readonly backgroundColor: string | null\n readonly accentColor: string | null\n readonly backdropEnabled: boolean\n readonly ctas: ReadonlyArray<InAppCta>\n\n readonly startAt: string | null\n readonly endAt: string | null\n readonly createdAt: string\n readonly updatedAt: string\n}\n\nexport interface CreateInAppMessageRequest {\n readonly personalization?: PersonalizationSpec | null\n readonly deliveryPlatforms?: ReadonlyArray<\n import('./web.js').DeliveryPlatform\n >\n readonly webPresentation?: import('./web.js').WebPresentation | null\n readonly name: string\n readonly audienceSegmentId?: string | null\n readonly audience?: AudienceSpec\n readonly trigger?: TriggerSpec\n readonly triggerEventName?: string | null\n readonly screenAllowlist?: ReadonlyArray<string>\n readonly screenDenylist?: ReadonlyArray<string>\n readonly frequency?: InAppFrequency\n readonly conversionGoalEvent?: string | null\n readonly conversionWindowHours?: number\n readonly priority?: number\n readonly forceShow?: boolean\n readonly autoDismissSeconds?: number | null\n readonly format: InAppMessageFormat\n readonly title: string\n readonly body?: string | null\n readonly imageUrl?: string | null\n readonly themeMode?: ThemeMode\n readonly backgroundColor?: string | null\n readonly accentColor?: string | null\n readonly backdropEnabled?: boolean\n readonly ctas?: ReadonlyArray<InAppCta>\n readonly startAt?: string | null\n readonly endAt?: string | null\n readonly status?: InAppMessageStatus\n}\n\nexport interface UpdateInAppMessageRequest\n extends Partial<CreateInAppMessageRequest> {\n readonly status?: InAppMessageStatus\n}\n\nexport interface InAppMessageAnalytics {\n readonly totals: {\n readonly impressions: number\n readonly dismissed: number\n readonly autoDismissed: number\n readonly ctaClicked: number\n }\n readonly timeline: ReadonlyArray<{\n readonly day: string\n readonly impressions: number\n readonly dismissed: number\n readonly ctaClicked: number\n }>\n}\n\n// Subset of the message the SDK needs at render time. Mirrors\n// `ArmedTrigger.prompt` for feedback prompts — strips fields the device\n// doesn't need (audit columns, segment id) and leaves what the renderer\n// uses.\nexport interface ArmedInAppMessage {\n readonly personalization?:\n | import('./personalization.js').PersonalizationSpec\n | null\n readonly deliveryPlatforms?: ReadonlyArray<\n import('./web.js').DeliveryPlatform\n >\n readonly webPresentation?: import('./web.js').WebPresentation | null\n readonly messageId: string\n readonly eventName: string\n /** True only when the SDK can make the same targeting decision locally. */\n readonly clientSideEligible?: boolean\n readonly format: InAppMessageFormat\n readonly title: string\n readonly body: string | null\n readonly imageUrl: string | null\n readonly themeMode?: ThemeMode\n readonly backgroundColor: string | null\n readonly accentColor: string | null\n /** Defaults to true when omitted by an older API/cache payload. */\n readonly backdropEnabled?: boolean\n readonly ctas: ReadonlyArray<InAppCta>\n readonly autoDismissSeconds: number | null\n readonly screenAllowlist: ReadonlyArray<string>\n readonly screenDenylist: ReadonlyArray<string>\n readonly forceShow: boolean\n}\n","// ============================================================\n// Feature requests (5th pillar) — public types\n// ============================================================\n// Shared between API, dashboard, web-roadmap, and SDKs.\n// All shapes are `readonly`. Identity uses anonymousId + externalId\n// as on every other SDK payload — no new identity types here.\n\nimport type { ThemeMode } from './brand.js'\n\nexport type RequestStatus =\n | 'under_review'\n | 'planned'\n | 'in_progress'\n | 'shipped'\n | 'declined'\n\nexport type RequestFollowSource = 'upvote_auto' | 'manual'\n\nexport type RequestSort = 'top' | 'newest' | 'recently_updated'\n\nexport type RequestPersonalFilter = 'submitted' | 'upvoted' | 'following'\n\n// Event-name constants for the 7 events emitted by the request engine.\n// All flow through services/ingest.ts and become segmentable like every\n// other event (no segment-engine code changes needed).\nexport const REQUEST_SUBMITTED_EVENT_NAME = '$request_submitted' as const\nexport const REQUEST_UPVOTED_EVENT_NAME = '$request_upvoted' as const\nexport const REQUEST_UNUPVOTED_EVENT_NAME = '$request_unupvoted' as const\nexport const REQUEST_FOLLOWED_EVENT_NAME = '$request_followed' as const\nexport const REQUEST_UNFOLLOWED_EVENT_NAME = '$request_unfollowed' as const\nexport const REQUEST_STATUS_CHANGED_EVENT_NAME = '$request_status_changed' as const\nexport const REQUEST_RESPONDED_EVENT_NAME = '$request_responded' as const\nexport const REQUEST_COMMENTED_EVENT_NAME = '$request_commented' as const\nexport const REQUEST_COMMENT_EDITED_EVENT_NAME = '$request_comment_edited' as const\nexport const REQUEST_COMMENT_DELETED_EVENT_NAME = '$request_comment_deleted' as const\n\n// ---------- core domain shapes ----------\n\n/**\n * A feature request with viewer-relative state attached. Returned from\n * detail and list endpoints; `viewer*` fields are computed server-side\n * from the caller's identity.\n */\nexport interface Request {\n readonly id: string\n readonly appId: string\n readonly title: string\n readonly description: string\n readonly status: RequestStatus\n readonly devResponse: string | null\n readonly upvoteCount: number\n readonly followerCount: number\n readonly createdAt: string\n readonly updatedAt: string\n readonly statusChangedAt: string\n readonly lastRespondedAt: string | null\n readonly viewerHasUpvoted: boolean\n readonly viewerIsFollowing: boolean\n readonly viewerIsSubmitter: boolean\n}\n\n/** Compact summary used in list views and search typeahead. */\nexport interface RequestSummary {\n readonly id: string\n readonly title: string\n readonly description: string\n readonly status: RequestStatus\n readonly upvoteCount: number\n readonly followerCount: number\n readonly createdAt: string\n readonly statusChangedAt: string\n readonly viewerHasUpvoted: boolean\n readonly viewerIsFollowing: boolean\n /** Dashboard-only publication metadata. Omitted from SDK responses. */\n readonly portalVisible?: boolean\n readonly source?: 'sdk' | 'portal'\n readonly hidden?: boolean\n readonly devResponse?: string | null\n}\n\n/** Search-as-you-type result; the SDK shows up to 5. */\nexport interface RequestSearchResult {\n readonly id: string\n readonly title: string\n readonly status: RequestStatus\n readonly upvoteCount: number\n}\n\n// ---------- toggle return shapes ----------\n\n/** Returned from POST/DELETE /v1/sdk/requests/:id/votes. */\nexport interface RequestVote {\n readonly requestId: string\n readonly upvoted: boolean\n readonly followed: boolean\n readonly upvoteCount: number\n readonly followerCount: number\n}\n\n/** Returned from POST/DELETE /v1/sdk/requests/:id/follows. */\nexport interface RequestFollow {\n readonly requestId: string\n readonly following: boolean\n readonly followerCount: number\n readonly source: RequestFollowSource\n}\n\n// ---------- request payloads ----------\n\nexport interface GetRequestsOptions {\n readonly sort?: RequestSort\n readonly statuses?: ReadonlyArray<RequestStatus>\n readonly mine?: RequestPersonalFilter\n readonly q?: string\n readonly cursor?: string | null\n readonly limit?: number\n}\n\nexport interface GetRequestsResult {\n readonly items: ReadonlyArray<RequestSummary>\n readonly nextCursor: string | null\n}\n\nexport interface SubmitRequestPayload {\n readonly anonymousId: string\n readonly externalId?: string | null\n readonly title: string\n readonly description: string\n}\n\nexport interface RequestVotePayload {\n readonly anonymousId: string\n readonly externalId?: string | null\n}\n\nexport interface RequestFollowPayload {\n readonly anonymousId: string\n readonly externalId?: string | null\n}\n\n// ---------- dashboard shapes ----------\n\nexport interface RequestDetail extends Request {\n readonly submitterAnonymousId: string\n readonly submitterExternalId: string | null\n readonly hidden: boolean\n readonly portalVisible?: boolean\n readonly source?: 'sdk' | 'portal'\n readonly portalVisitorEmail?: string | null\n}\n\nexport interface RequestUpvoterSegmentBreakdown {\n readonly requestId: string\n readonly totalUpvoters: number\n readonly segments: ReadonlyArray<{\n readonly segmentId: string\n readonly segmentName: string\n readonly count: number\n readonly percentage: number\n }>\n}\n\nexport type RequestTimelineEntryKind =\n | 'submitted'\n | 'upvote_burst'\n | 'follow_burst'\n | 'status_changed'\n | 'responded'\n\nexport interface RequestTimelineEntry {\n readonly kind: RequestTimelineEntryKind\n readonly at: string\n readonly count?: number\n readonly fromStatus?: RequestStatus\n readonly toStatus?: RequestStatus\n readonly responseExcerpt?: string\n}\n\nexport interface RequestAnalytics {\n readonly submissions: ReadonlyArray<{ readonly date: string; readonly count: number }>\n readonly upvotes: ReadonlyArray<{ readonly date: string; readonly count: number }>\n readonly follows: ReadonlyArray<{ readonly date: string; readonly count: number }>\n readonly statusDistribution: Record<RequestStatus, number>\n readonly devResponseRate: number\n readonly medianResponseHours: number | null\n readonly leaderboard: ReadonlyArray<{\n readonly anonymousId: string\n readonly externalId: string | null\n readonly submissions: number\n readonly upvotes: number\n }>\n}\n\nexport interface UpdateRequestStatusRequest {\n readonly status: RequestStatus\n readonly responseAppend?: string\n}\n\nexport interface UpdateRequestResponseRequest {\n readonly body: string\n}\n\nexport interface UpdateRequestModerationRequest {\n readonly hidden: boolean\n}\n\nexport interface MergeRequestsRequest {\n readonly canonicalId: string\n readonly duplicateIds: ReadonlyArray<string>\n}\n\nexport interface BulkUpdateStatusRequest {\n readonly ids: ReadonlyArray<string>\n readonly status: RequestStatus\n}\n\nexport interface ListRequestsQuery {\n readonly sort?: RequestSort\n readonly status?: RequestStatus | ReadonlyArray<RequestStatus>\n readonly filter?: RequestPersonalFilter\n readonly anonymousId?: string\n readonly q?: string\n readonly hidden?: boolean\n readonly page?: number\n readonly limit?: number\n}\n\n// ---------- settings ----------\n\nexport interface RequestBranding {\n readonly logoUrl?: string | null\n readonly accentColor?: string | null\n readonly coverImageUrl?: string | null\n readonly introCopy?: string | null\n}\n\nexport interface RequestNotificationRules {\n readonly transitions?: Record<string, boolean>\n readonly responseFirst?: boolean\n readonly responseEdit?: boolean\n readonly templateOverrides?: {\n readonly statusChange?: string\n readonly response?: string\n }\n}\n\nexport interface RequestSettings {\n readonly appId: string\n readonly enabled: boolean\n readonly entryLabel: string\n readonly viewSegmentId: string | null\n readonly submitSegmentId: string | null\n readonly publicRoadmapEnabled: boolean\n readonly publicSlug: string | null\n readonly themeMode: ThemeMode\n readonly branding: RequestBranding\n readonly notificationRules: RequestNotificationRules\n}\n\nexport interface UpdateRequestSettingsRequest {\n readonly enabled?: boolean\n readonly entryLabel?: string\n readonly viewSegmentId?: string | null\n readonly submitSegmentId?: string | null\n readonly publicRoadmapEnabled?: boolean\n readonly publicSlug?: string | null\n readonly themeMode?: ThemeMode\n readonly branding?: RequestBranding\n readonly notificationRules?: RequestNotificationRules\n}\n\n// ---------- public web roadmap shapes ----------\n\n/** Public-safe request summary (no submitter identity). */\nexport interface RequestPublicSummary {\n readonly id: string\n readonly title: string\n readonly description: string\n readonly status: RequestStatus\n readonly upvoteCount: number\n readonly followerCount: number\n readonly createdAt: string\n readonly statusChangedAt: string\n}\n\nexport interface RequestPublicDetail extends RequestPublicSummary {\n readonly devResponse: string | null\n readonly lastRespondedAt: string | null\n}\n\nexport interface RequestPublicBranding {\n readonly entryLabel: string\n readonly appName: string\n readonly branding: RequestBranding\n readonly fallbackInstallUrl: string | null\n}\n\n// ---------- SDK push payload ----------\n\n/** Carried inside push/in-app message payloads when status changes. */\nexport interface RequestStatusChangedNotice {\n readonly requestId: string\n readonly title: string\n readonly oldStatus: RequestStatus\n readonly newStatus: RequestStatus\n readonly devResponseExcerpt?: string\n readonly receivedVia: 'push' | 'inapp'\n}\n\n// ---------- comments ----------\n\nexport interface RequestComment {\n readonly id: string\n readonly requestId: string\n readonly body: string\n readonly authorAnonymousId: string\n readonly authorExternalId: string | null\n readonly viewerIsAuthor: boolean\n readonly createdAt: string\n readonly updatedAt: string\n}\n\nexport interface PostCommentPayload {\n readonly anonymousId: string\n readonly externalId?: string | null\n readonly body: string\n}\n\nexport interface EditCommentPayload {\n readonly anonymousId: string\n readonly body: string\n}\n\n/** Host-app callbacks registered via `setRequestsHandlers`. */\nexport interface RequestsHandlers {\n readonly onSubmit?: (request: Request) => void\n readonly onVote?: (vote: RequestVote) => void\n readonly onFollow?: (follow: RequestFollow) => void\n readonly onStatusChanged?: (notice: RequestStatusChangedNotice) => void\n}\n","// ==========================================================\n// Inline targeting spec — used by feedback prompts, surveys,\n// and push campaigns. Wraps each pillar record with an\n// `AudienceSpec` (who) + `TriggerSpec` (when).\n//\n// One condition kind in `AudienceCondition` is `segment`,\n// which references saved Segments by id (so the dashboard\n// suggests existing segments in that one branch). All other\n// kinds are evaluated inline against user properties or\n// recent event aggregates.\n//\n// `TriggerSpec` is a discriminated union with a shared base\n// (`app_open`, `event`, `audience_join`). Pillar packages\n// add extra kinds locally (e.g. push adds `manual` /\n// `scheduled`) — engines `switch` on `kind` and treat\n// unknowns as no-op.\n// ==========================================================\n\nimport type { ComparisonOp } from './segment-dsl.js'\n\nexport type Platform = 'ios' | 'android' | 'web'\n\nexport type AudienceCombinator = 'all' | 'any'\n\nexport type AudienceMode = 'everyone' | 'match'\n\n// -------------------- Audience conditions ----------------\n\nexport interface SegmentCondition {\n readonly kind: 'segment'\n readonly op: 'is' | 'is_not'\n readonly segmentIds: ReadonlyArray<string>\n}\n\nexport interface CountryCondition {\n readonly kind: 'country'\n readonly op: 'is_any_of' | 'is_none_of'\n readonly values: ReadonlyArray<string> // ISO 3166-1 alpha-2\n}\n\nexport interface LastActiveCondition {\n readonly kind: 'last_active'\n readonly op: 'within_days' | 'before_days' | 'never'\n readonly days?: number\n}\n\nexport interface InstallDateCondition {\n readonly kind: 'install_date'\n // `*_days` operators are relative to today; `*_date` and `between`\n // pin to user-picked calendar dates (ISO yyyy-mm-dd).\n readonly op:\n | 'within_days'\n | 'before_days'\n | 'after_date'\n | 'before_date'\n | 'between'\n readonly days?: number\n readonly date?: string // ISO date — used by after_date / before_date\n readonly from?: string // ISO date — used by between\n readonly to?: string // ISO date — used by between\n}\n\nexport interface PlatformCondition {\n readonly kind: 'platform'\n readonly op: 'is' | 'is_not'\n readonly values: ReadonlyArray<Platform>\n}\n\nexport interface UserPropertyCondition {\n readonly kind: 'user_property'\n readonly key: string\n readonly op: ComparisonOp\n readonly value?: string | number | boolean | ReadonlyArray<string | number>\n}\n\nexport interface EventPropertyFilter {\n readonly key: string\n readonly op: ComparisonOp\n readonly value?: string | number | boolean | ReadonlyArray<string | number>\n}\n\nexport interface EventPerformedCondition {\n readonly kind: 'event_performed'\n readonly op: 'did' | 'did_not'\n readonly eventName: string\n /** @deprecated Kept so previously saved audience definitions still load. */\n readonly property?: EventPropertyFilter\n readonly propertyFilters?: ReadonlyArray<EventPropertyFilter>\n readonly windowDays?: number\n readonly minCount?: number\n}\n\nexport interface AppVersionCondition {\n readonly kind: 'app_version'\n // String comparison for v1 — \"2.10.0\" sorts before \"2.9.0\" lexically.\n // Acceptable until we ship a semver-aware compare; the dashboard\n // input warns users.\n readonly op: 'eq' | 'neq' | 'gte' | 'lte' | 'gt' | 'lt'\n readonly version: string\n}\n\nexport type AudienceCondition =\n | SegmentCondition\n | CountryCondition\n | LastActiveCondition\n | InstallDateCondition\n | PlatformCondition\n | UserPropertyCondition\n | EventPerformedCondition\n | AppVersionCondition\n\nexport type AudienceConditionKind = AudienceCondition['kind']\n\nexport interface AudienceSpec {\n readonly version: 1\n readonly mode: AudienceMode\n readonly combinator: AudienceCombinator\n readonly conditions: ReadonlyArray<AudienceCondition>\n}\n\nexport function emptyAudienceSpec(): AudienceSpec {\n return { version: 1, mode: 'everyone', combinator: 'all', conditions: [] }\n}\n\n// -------------------- Trigger spec -----------------------\n\nexport type TriggerOccurrenceMode = 'every' | 'after_nth' | 'first_only'\n\nexport interface TriggerOccurrence {\n readonly mode: TriggerOccurrenceMode\n readonly n?: number // required when mode === 'after_nth'\n}\n\nexport interface ActiveWindow {\n readonly startAt?: string // ISO datetime\n readonly endAt?: string // ISO datetime\n}\n\nexport interface AppOpenTrigger {\n readonly kind: 'app_open'\n readonly delaySeconds?: number\n readonly onceOnly?: boolean\n readonly activeWindow?: ActiveWindow\n}\n\nexport interface EventTrigger {\n readonly kind: 'event'\n readonly eventName: string\n readonly propertyFilters?: ReadonlyArray<EventPropertyFilter>\n readonly occurrence?: TriggerOccurrence\n readonly delaySeconds?: number\n readonly onceOnly?: boolean\n readonly activeWindow?: ActiveWindow\n}\n\nexport interface AudienceJoinTrigger {\n readonly kind: 'audience_join'\n readonly delaySeconds?: number\n readonly onceOnly?: boolean\n readonly activeWindow?: ActiveWindow\n}\n\nexport interface AppVersionChangedTrigger {\n readonly kind: 'app_version_changed'\n readonly delaySeconds?: number\n readonly onceOnly?: boolean\n readonly activeWindow?: ActiveWindow\n}\n\nexport type TriggerSpec =\n | AppOpenTrigger\n | EventTrigger\n | AudienceJoinTrigger\n | AppVersionChangedTrigger\n\nexport type TriggerKind = TriggerSpec['kind']\n\n/**\n * Synthetic event name the SDK emits whenever the host app cold-starts\n * or transitions from background to foreground. The trigger engine\n * indexes `app_open`-kind prompts under this name so the same matching\n * pipeline handles both event-driven and lifecycle-driven prompts.\n */\nexport const APP_OPEN_EVENT_NAME = '$app_open'\n\n/**\n * Synthetic event the engine indexes `audience_join` campaigns under.\n * Mirrors APP_OPEN_EVENT_NAME so the same matching pipeline handles\n * both lifecycle and audience-membership triggers.\n */\nexport const AUDIENCE_JOIN_EVENT_NAME = '$audience_join'\n\nexport const AUDIENCE_JOIN_TRIGGER_KIND: AudienceJoinTrigger['kind'] = 'audience_join'\n\n/**\n * Synthetic event the SDK emits on cold-start when the persisted app\n * version differs from the running binary's version. Lets in-app\n * messages (and feedback / surveys) target users right after an update\n * — e.g. \"What's new\" modals.\n */\nexport const APP_VERSION_CHANGED_EVENT_NAME = '$app_version_changed'\n\nexport function defaultTriggerSpec(): TriggerSpec {\n return { kind: 'app_open' }\n}\n\nexport function defaultEventTrigger(eventName = ''): EventTrigger {\n return {\n kind: 'event',\n eventName,\n occurrence: { mode: 'every' },\n }\n}\n","// ==========================================================\n// Preset themes for the Feedback Design step. 12 curated\n// presets + a custom-your-own option in the UI. Each preset\n// surfaces 3 swatches in the gallery card for quick scan.\n// ==========================================================\n\nexport interface ThemeColors {\n readonly primary: string\n readonly background: string\n readonly text: string\n readonly subtext: string\n readonly border: string\n readonly accent?: string\n readonly button?: string\n}\n\nexport type CornerRadiusPreset = 'sharp' | 'soft' | 'rounded' | 'pill'\n\nexport const RADIUS_PRESETS: Record<CornerRadiusPreset, number> = {\n sharp: 4,\n soft: 12,\n rounded: 20,\n pill: 999,\n}\n\nexport interface ThemePreset {\n readonly id: string\n readonly name: string\n readonly description: string\n readonly colors: ThemeColors\n readonly radius: number\n readonly fontFamily: string\n readonly swatches: readonly [string, string, string]\n}\n\n// Default font family for every preset. Matches the SDK's\n// DEFAULT_THEME so a freshly-saved theme renders the same in the\n// dashboard preview (web font loaded via next/font + Google Fonts\n// stylesheet) and on the mobile app (host bundles the .ttf via\n// react-native.config.js). Previously the presets used 'Inter',\n// which neither side had loaded — both fell back to system sans,\n// so designers saw a font drift between the dashboard and device.\nconst JAKARTA = 'Plus Jakarta Sans'\n\nexport const THEME_PRESETS: ReadonlyArray<ThemePreset> = [\n {\n id: 'minimal',\n name: 'Minimal',\n description: 'Clean neutral palette',\n colors: {\n primary: '#111827',\n background: '#FFFFFF',\n text: '#111827',\n subtext: '#6B7280',\n border: '#E5E7EB',\n button: '#111827',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#111827', '#FFFFFF', '#E5E7EB'],\n },\n {\n id: 'ocean',\n name: 'Ocean',\n description: 'Cool blue tones',\n colors: {\n primary: '#0EA5E9',\n background: '#F0F9FF',\n text: '#0C4A6E',\n subtext: '#0369A1',\n border: '#BAE6FD',\n button: '#0EA5E9',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#0EA5E9', '#0C4A6E', '#BAE6FD'],\n },\n {\n id: 'sunset',\n name: 'Sunset',\n description: 'Warm orange glow',\n colors: {\n primary: '#F97316',\n background: '#FFF7ED',\n text: '#7C2D12',\n subtext: '#C2410C',\n border: '#FED7AA',\n button: '#F97316',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#F97316', '#7C2D12', '#FED7AA'],\n },\n {\n id: 'forest',\n name: 'Forest',\n description: 'Natural green hues',\n colors: {\n primary: '#16A34A',\n background: '#F0FDF4',\n text: '#14532D',\n subtext: '#166534',\n border: '#BBF7D0',\n button: '#16A34A',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#16A34A', '#14532D', '#BBF7D0'],\n },\n {\n id: 'midnight',\n name: 'Midnight',\n description: 'Deep dark mode',\n colors: {\n primary: '#A78BFA',\n background: '#0F172A',\n text: '#F8FAFC',\n subtext: '#94A3B8',\n border: '#1E293B',\n button: '#A78BFA',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#A78BFA', '#0F172A', '#1E293B'],\n },\n {\n id: 'candy',\n name: 'Candy',\n description: 'Playful pink + violet',\n colors: {\n primary: '#EC4899',\n background: '#FDF2F8',\n text: '#831843',\n subtext: '#BE185D',\n border: '#FBCFE8',\n button: '#EC4899',\n },\n radius: 20,\n fontFamily: JAKARTA,\n swatches: ['#EC4899', '#831843', '#FBCFE8'],\n },\n {\n id: 'mono',\n name: 'Mono',\n description: 'High-contrast B&W',\n colors: {\n primary: '#000000',\n background: '#FFFFFF',\n text: '#000000',\n subtext: '#525252',\n border: '#000000',\n button: '#000000',\n },\n radius: 4,\n fontFamily: JAKARTA,\n swatches: ['#000000', '#FFFFFF', '#525252'],\n },\n {\n id: 'coral',\n name: 'Coral',\n description: 'Soft coral accent',\n colors: {\n primary: '#FB7185',\n background: '#FFF1F2',\n text: '#881337',\n subtext: '#9F1239',\n border: '#FECDD3',\n button: '#FB7185',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#FB7185', '#881337', '#FECDD3'],\n },\n {\n id: 'ink',\n name: 'Ink',\n description: 'Deep navy editorial',\n colors: {\n primary: '#1E3A8A',\n background: '#F8FAFC',\n text: '#0F172A',\n subtext: '#475569',\n border: '#CBD5E1',\n button: '#1E3A8A',\n },\n radius: 12,\n fontFamily: JAKARTA,\n swatches: ['#1E3A8A', '#0F172A', '#CBD5E1'],\n },\n {\n id: 'mint',\n name: 'Mint',\n description: 'Fresh teal vibe',\n colors: {\n primary: '#14B8A6',\n background: '#F0FDFA',\n text: '#134E4A',\n subtext: '#0F766E',\n border: '#99F6E4',\n button: '#14B8A6',\n },\n radius: 16,\n fontFamily: JAKARTA,\n swatches: ['#14B8A6', '#134E4A', '#99F6E4'],\n },\n {\n id: 'slate',\n name: 'Slate',\n description: 'Quiet professional',\n colors: {\n primary: '#475569',\n background: '#F1F5F9',\n text: '#0F172A',\n subtext: '#64748B',\n border: '#CBD5E1',\n button: '#475569',\n },\n radius: 12,\n fontFamily: JAKARTA,\n swatches: ['#475569', '#0F172A', '#CBD5E1'],\n },\n {\n id: 'aurora',\n name: 'Aurora',\n description: 'Vibrant gradient pop',\n colors: {\n primary: '#8B5CF6',\n background: '#FAF5FF',\n text: '#3B0764',\n subtext: '#7E22CE',\n border: '#E9D5FF',\n accent: '#EC4899',\n button: '#8B5CF6',\n },\n radius: 20,\n fontFamily: JAKARTA,\n swatches: ['#8B5CF6', '#EC4899', '#E9D5FF'],\n },\n] as const\n\nexport function getThemePresetById(id: string): ThemePreset | undefined {\n return THEME_PRESETS.find((preset) => preset.id === id)\n}\n\nexport function defaultThemePreset(): ThemePreset {\n // The presets list is non-empty by construction; assert via index access.\n return THEME_PRESETS[0] as ThemePreset\n}\n","import type { PromptTheme } from './prompt.js'\nimport type { ThemePreset } from './themes.js'\n\nexport type BrandPillar = 'feedback' | 'survey' | 'inapp' | 'requests'\nexport type ThemeMode = 'app_default' | 'custom'\n\nexport interface BrandThemeTokens {\n readonly colors: {\n readonly primary: string\n readonly background: string\n readonly text: string\n readonly subtext: string\n readonly border: string\n }\n readonly radius: number\n readonly fontFamily: string\n}\n\nexport type BrandThemeRef = `preset:${string}` | `custom:${string}`\n\nexport interface BrandTheme {\n readonly ref: BrandThemeRef\n readonly id: string\n readonly kind: 'preset' | 'custom'\n readonly name: string\n readonly description?: string\n readonly tokens: BrandThemeTokens\n readonly swatches: readonly [string, string, string]\n readonly editable: boolean\n readonly assignedPillars: ReadonlyArray<BrandPillar>\n readonly createdAt?: string\n readonly updatedAt?: string\n}\n\nexport type BrandThemeDefaults = Readonly<Record<BrandPillar, BrandThemeRef>>\n\nexport interface AppBrandSettings {\n readonly appId: string\n readonly themes: ReadonlyArray<BrandTheme>\n readonly defaults: BrandThemeDefaults\n readonly resolvedDefaults: Readonly<Record<BrandPillar, BrandThemeTokens>>\n readonly updatedAt: string\n}\n\nexport interface CreateBrandThemeRequest {\n readonly name: string\n readonly tokens: BrandThemeTokens\n}\n\nexport interface UpdateBrandThemeRequest {\n readonly name?: string\n readonly tokens?: BrandThemeTokens\n}\n\nexport interface UpdateBrandThemeDefaultsRequest {\n readonly defaults: BrandThemeDefaults\n}\n\nexport function brandTokensFromPreset(\n preset: Pick<ThemePreset, 'colors' | 'radius' | 'fontFamily'>,\n): BrandThemeTokens {\n return {\n colors: {\n primary: preset.colors.primary,\n background: preset.colors.background,\n text: preset.colors.text,\n subtext: preset.colors.subtext,\n border: preset.colors.border,\n },\n radius: preset.radius,\n fontFamily: preset.fontFamily,\n }\n}\n\nexport function promptThemeFromBrandTokens(tokens: BrandThemeTokens): PromptTheme {\n return {\n colors: { ...tokens.colors },\n radius: tokens.radius,\n fontFamily: tokens.fontFamily,\n }\n}\n\nexport function inAppColorsFromBrandTokens(tokens: BrandThemeTokens): {\n readonly backgroundColor: string\n readonly accentColor: string\n} {\n return {\n backgroundColor: tokens.colors.background,\n accentColor: tokens.colors.primary,\n }\n}\n\nexport function requestAccentFromBrandTokens(tokens: BrandThemeTokens): string {\n return tokens.colors.primary\n}\n","import type { EventPropertyValue } from './event.js'\n\nexport const INTEGRATION_PROVIDERS = ['amplitude', 'mixpanel'] as const\nexport type IntegrationProvider = (typeof INTEGRATION_PROVIDERS)[number]\n\nexport const INTEGRATION_CATEGORIES = [\n 'feedback', 'surveys', 'inapp', 'push', 'requests', 'lifecycle',\n] as const\nexport type IntegrationCategory = (typeof INTEGRATION_CATEGORIES)[number]\n\nexport type IntegrationStatus = 'connected' | 'paused' | 'needs_attention' | 'disconnected'\nexport type AmplitudeIntegrationRegion = 'us' | 'eu'\nexport type MixpanelIntegrationRegion = 'us' | 'eu' | 'in'\nexport type IntegrationRegion = 'us' | 'eu' | 'in'\nexport type IntegrationDeliveryStatus =\n | 'pending' | 'leased' | 'retrying' | 'delivered' | 'dead_lettered' | 'skipped'\nexport type CoreEventSubjectRole = 'actor' | 'affected_user'\n\nexport interface CoreIntegrationEventDefinition {\n readonly key: string\n readonly name: string\n readonly category: IntegrationCategory | 'identity'\n readonly subjectRole: CoreEventSubjectRole\n readonly required?: boolean\n /** Stable output property key -> accepted source property aliases. */\n readonly properties: Readonly<Record<string, ReadonlyArray<string>>>\n}\n\nexport const USER_IDENTIFIED_EVENT_NAME = '$user_identified' as const\n\nfunction camelize(value: string): string {\n return value.replace(/_([a-z])/g, (_match, letter: string) => letter.toUpperCase())\n}\n\nconst ids = (...keys: string[]): Readonly<Record<string, ReadonlyArray<string>>> =>\n Object.fromEntries(keys.map((key) => [key, [key, camelize(key)]]))\n\nconst pushEvents: ReadonlyArray<readonly [string, string]> = [\n ['$push_sent', 'UserGist Push Sent'],\n ['$push_delivered', 'UserGist Push Delivered'],\n ['$push_received', 'UserGist Push Received'],\n ['$push_displayed', 'UserGist Push Displayed'],\n ['$push_opened', 'UserGist Push Opened'],\n ['$push_dismissed', 'UserGist Push Dismissed'],\n ['$push_clicked', 'UserGist Push Clicked'],\n ['$push_action_clicked', 'UserGist Push Action Clicked'],\n ['$push_bounced', 'UserGist Push Bounced'],\n]\n\nconst requestEvents: ReadonlyArray<readonly [string, string, CoreEventSubjectRole]> = [\n ['$request_submitted', 'UserGist Request Submitted', 'actor'],\n ['$request_upvoted', 'UserGist Request Upvoted', 'actor'],\n ['$request_unupvoted', 'UserGist Request Unupvoted', 'actor'],\n ['$request_followed', 'UserGist Request Followed', 'actor'],\n ['$request_unfollowed', 'UserGist Request Unfollowed', 'actor'],\n ['$request_status_changed', 'UserGist Request Status Changed', 'affected_user'],\n ['$request_responded', 'UserGist Request Responded', 'affected_user'],\n ['$request_commented', 'UserGist Request Commented', 'actor'],\n ['$request_comment_edited', 'UserGist Request Comment Edited', 'actor'],\n ['$request_comment_deleted', 'UserGist Request Comment Deleted', 'affected_user'],\n]\n\nconst answerProperties: Readonly<Record<string, ReadonlyArray<string>>> = {\n ...ids(\n 'question_id',\n 'question_type',\n 'question_title',\n 'answer_format',\n 'answer_present',\n 'answer_numeric_value',\n 'answer_selection_count',\n 'answer_text_length',\n ),\n // These aliases are generated only by the trusted server response paths.\n // The API delivery boundary removes them from public SDK events before this\n // normalizer runs. The complete answer_value stays in UserGist; destinations\n // receive a value only for server-verified structured data.\n answer_value: ['__usergist_destination_answer_value'],\n answer_display_value: ['__usergist_destination_answer_display_value'],\n}\n\nexport const CORE_INTEGRATION_EVENTS: ReadonlyArray<CoreIntegrationEventDefinition> = [\n { key: '$app_open', name: 'UserGist App Opened', category: 'lifecycle', subjectRole: 'actor', properties: {} },\n { key: '$app_version_changed', name: 'UserGist App Version Changed', category: 'lifecycle', subjectRole: 'actor', properties: { ...ids('old_version', 'new_version') } },\n { key: USER_IDENTIFIED_EVENT_NAME, name: 'UserGist User Identified', category: 'identity', subjectRole: 'actor', required: true, properties: {} },\n { key: '$feedback_prompt_shown', name: 'UserGist Feedback Prompt Shown', category: 'feedback', subjectRole: 'actor', properties: { ...ids('prompt_id') } },\n { key: '$feedback_response', name: 'UserGist Feedback Response Submitted', category: 'feedback', subjectRole: 'actor', properties: { ...ids('response_id', 'prompt_id', 'prompt_name', 'dismissed', 'latency_ms', 'answer_count', 'feedback_types') } },\n { key: '$feedback_answer_submitted', name: 'UserGist Feedback Answer Submitted', category: 'feedback', subjectRole: 'actor', properties: { ...ids('response_id', 'prompt_id', 'prompt_name'), ...answerProperties } },\n { key: '$survey_started', name: 'UserGist Survey Started', category: 'surveys', subjectRole: 'actor', properties: { ...ids('campaign_id', 'survey_name', 'attempt_id', 'language', 'source') } },\n { key: '$survey_answer_submitted', name: 'UserGist Survey Answer Submitted', category: 'surveys', subjectRole: 'actor', properties: { ...ids('response_id', 'campaign_id', 'survey_name', 'attempt_id', 'language'), ...answerProperties } },\n { key: '$survey_completed', name: 'UserGist Survey Completed', category: 'surveys', subjectRole: 'actor', properties: { ...ids('campaign_id', 'survey_name', 'attempt_id', 'language', 'source', 'duration_ms') } },\n { key: '$survey_abandoned', name: 'UserGist Survey Abandoned', category: 'surveys', subjectRole: 'actor', properties: { ...ids('campaign_id', 'survey_name', 'attempt_id', 'language', 'source', 'duration_ms') } },\n { key: '$inapp_shown', name: 'UserGist In-App Message Shown', category: 'inapp', subjectRole: 'actor', properties: { ...ids('message_id') } },\n { key: '$inapp_dismissed', name: 'UserGist In-App Message Dismissed', category: 'inapp', subjectRole: 'actor', properties: { ...ids('message_id', 'dismiss_reason') } },\n { key: '$inapp_auto_dismissed', name: 'UserGist In-App Message Auto-Dismissed', category: 'inapp', subjectRole: 'actor', properties: { ...ids('message_id', 'dismiss_reason') } },\n { key: '$inapp_cta_clicked', name: 'UserGist In-App Message CTA Clicked', category: 'inapp', subjectRole: 'actor', properties: { ...ids('message_id', 'cta_id', 'cta_index'), action: ['action', 'cta_action'] } },\n ...pushEvents.map(([key, name]) => ({\n key,\n name,\n category: 'push' as const,\n subjectRole: 'actor' as const,\n properties: {\n ...ids('delivery_id', 'campaign_id', 'delivery_state', 'failure_code'),\n action_id: ['action_id', 'actionId', 'action_button', 'actionButton'],\n },\n })),\n ...requestEvents.map(([key, name, subjectRole]) => ({ key, name, category: 'requests' as const, subjectRole, properties: { ...ids('request_id', 'comment_id', 'source', 'old_status', 'new_status', 'deleted_by'), usergist_actor_type: ['usergist_actor_type', 'actor_type'] } })),\n]\n\nconst CORE_EVENT_BY_KEY = new Map(CORE_INTEGRATION_EVENTS.map((event) => [event.key, event]))\n\nexport function getCoreIntegrationEvent(key: string): CoreIntegrationEventDefinition | null {\n return CORE_EVENT_BY_KEY.get(key) ?? null\n}\n\nexport function sanitizeCoreIntegrationProperties(\n definition: CoreIntegrationEventDefinition,\n input: Readonly<Record<string, unknown>> | null | undefined,\n): Readonly<Record<string, EventPropertyValue>> {\n if (!input) return {}\n const output: Record<string, EventPropertyValue> = {}\n for (const [outputKey, aliases] of Object.entries(definition.properties)) {\n const alias = aliases.find((candidate) => Object.prototype.hasOwnProperty.call(input, candidate))\n if (!alias) continue\n const value = input[alias]\n if (typeof value === 'string') output[outputKey] = value.slice(0, 1024)\n else if (typeof value === 'number' && Number.isFinite(value)) output[outputKey] = value\n else if (typeof value === 'boolean' || value === null) output[outputKey] = value\n }\n return output\n}\n\nexport interface IntegrationSummary {\n readonly id: string\n readonly provider: IntegrationProvider\n readonly status: IntegrationStatus\n readonly region: IntegrationRegion\n readonly categories: ReadonlyArray<IntegrationCategory>\n readonly credentialHint: string | null\n readonly connectedAt: string | null\n readonly pausedAt: string | null\n readonly lastVerifiedAt: string | null\n readonly lastSuccessAt: string | null\n readonly lastFailureAt: string | null\n readonly lastErrorCode: string | null\n readonly lastErrorMessage: string | null\n}\n\nexport type ConnectIntegrationRequest =\n | { readonly provider: 'amplitude'; readonly apiKey: string; readonly region: 'us' | 'eu'; readonly categories: ReadonlyArray<IntegrationCategory> }\n | { readonly provider: 'mixpanel'; readonly projectToken: string; readonly region: 'us' | 'eu' | 'in'; readonly categories: ReadonlyArray<IntegrationCategory>; readonly identityMode: 'simplified' }\n\nexport interface UpdateIntegrationRequest {\n readonly categories: ReadonlyArray<IntegrationCategory>\n}\n\nexport interface IntegrationTestResult {\n readonly accepted: true\n readonly eventName: 'UserGist Integration Connected'\n readonly deviceId: string\n readonly acceptedAt: string\n}\n\nexport interface IntegrationDeliverySummary {\n readonly id: string\n readonly eventKey: string\n readonly eventName: string\n readonly status: IntegrationDeliveryStatus\n readonly identity: { readonly anonymousId: string; readonly externalId: string | null }\n readonly occurredAt: string\n readonly attempts: number\n readonly providerStatusCode: number | null\n readonly lastErrorMessage: string | null\n}\n\nexport interface IntegrationDeliveriesResponse {\n readonly items: ReadonlyArray<IntegrationDeliverySummary>\n readonly nextCursor: string | null\n}\n","/**\n * Canonical event names emitted by the push pillar. These land in the\n * events pipeline so segments can query them like any other event.\n */\nexport const PUSH_EVENTS = {\n SENT: '$push_sent',\n DELIVERED: '$push_delivered',\n DISPLAYED: '$push_displayed',\n RECEIVED: '$push_received',\n OPENED: '$push_opened',\n DISMISSED: '$push_dismissed',\n CLICKED: '$push_clicked',\n ACTION_CLICKED: '$push_action_clicked',\n BOUNCED: '$push_bounced',\n SILENT_ACK: '$push_silent_ack',\n} as const\n\nexport type PushEventName = (typeof PUSH_EVENTS)[keyof typeof PUSH_EVENTS]\n","/**\n * Runtime types shared by the React Native, iOS, and Android SDKs for\n * the \"under the hood\" push primitives:\n * • Silent reachability ping payloads\n * • Delivery beacon contract (delivered / displayed / dismissed)\n * • Channel registry (Android NotificationChannel + iOS category)\n * • App-open beacon\n */\n\nexport interface SilentPushPayload {\n readonly usergist_silent: '1'\n readonly usergist_ping_id: string\n}\n\nexport type AndroidImportance = 0 | 1 | 2 | 3 | 4\n\nexport type ChannelCategory =\n | 'transactional'\n | 'marketing'\n | 'silent'\n | 'digest'\n | 'alert'\n\nexport interface PushChannelDef {\n readonly app_id: string\n readonly channel_id: string\n readonly display_name: string\n readonly description: string | null\n readonly importance: AndroidImportance\n readonly default_sound: string | null\n readonly default_vibrate: boolean\n readonly default_badge: boolean\n readonly category: ChannelCategory\n}\n\nexport interface DeliveryBeacon {\n readonly deliveryId: string\n readonly occurredAt?: string\n readonly attemptId?: string\n readonly actionButton?: string\n}\n\nexport type DeliveryBeaconKind =\n | 'delivered'\n | 'displayed'\n | 'dismissed'\n\nexport interface SilentAck {\n readonly pingId: string\n readonly anonymousId: string\n readonly receivedAt?: string\n}\n\nexport interface RebindRequest {\n readonly anonymousId: string\n readonly externalId: string\n readonly token: string\n}\n\nexport interface AppOpenBeacon {\n readonly anonymousId: string\n readonly occurredAt?: string\n}\n\n/**\n * SDK-side recognized payload after parsing a server-sent push. Both\n * APNs (via NSE) and FCM (via FirebaseMessagingService) decode into\n * this shape so the cross-platform UI/behaviour layer can stay\n * platform-agnostic.\n */\nexport interface ParsedPushPayload {\n readonly campaignId: string\n readonly variantId: string\n readonly deliveryId: string\n readonly title: string\n readonly body: string\n readonly imageUrl: string | null\n readonly deepLink: string | null\n readonly language: string | null\n readonly actionButtons: ReadonlyArray<{\n readonly label: string\n readonly action: 'open_app' | 'deep_link' | 'url' | 'dismiss'\n readonly target?: string\n }>\n readonly androidChannelId: string | null\n readonly silent: boolean\n readonly silentPingId: string | null\n}\n\n/**\n * Helper used by the data-only Android branch and the iOS NSE to\n * detect a silent reachability ping.\n */\nexport function isSilentPushPayload(\n raw: Record<string, unknown> | null | undefined,\n): boolean {\n if (!raw) return false\n return raw.usergist_silent === '1' && typeof raw.usergist_ping_id === 'string'\n}\n","import type {\n Predicate,\n PredicateGroup,\n SegmentDsl,\n UserPropertyPredicate,\n EventCountPredicate,\n EventOccurredPredicate,\n} from '../types/segment-dsl.js'\nimport type {\n SerializedSegmentRules,\n UserPropertyRule,\n} from '../types/prompt.js'\n\nexport interface UserState {\n readonly properties: Readonly<Record<string, string | number | boolean | null | undefined>>\n // eventCounts: eventName -> map of windowDays -> count\n readonly eventCounts: Readonly<Record<string, Readonly<Record<number, number>>>>\n // lastEventAt: eventName -> ISO timestamp (most recent)\n readonly lastEventAt: Readonly<Record<string, string | undefined>>\n}\n\n/**\n * Evaluate a segment DSL against a user snapshot.\n *\n * @param now - Reference timestamp (ms since epoch) used for time-window\n * predicates. MUST be supplied explicitly so evaluation is deterministic\n * across processes (server trigger engine + client SDK), independent of\n * wall-clock skew. Defaults to `Date.now()` for backwards compatibility,\n * but callers that care about parity should pass the same `now` they pass\n * to the matching server-side call.\n */\nexport function evaluateSegment(\n dsl: SegmentDsl,\n user: UserState,\n now: number = Date.now(),\n): boolean {\n return evaluateGroup(dsl.root, user, now)\n}\n\nfunction evaluateGroup(group: PredicateGroup, user: UserState, now: number): boolean {\n if (group.predicates.length === 0) return true\n if (group.combinator === 'AND') {\n return group.predicates.every((p) => evaluateNode(p, user, now))\n }\n return group.predicates.some((p) => evaluateNode(p, user, now))\n}\n\nfunction evaluateNode(node: Predicate | PredicateGroup, user: UserState, now: number): boolean {\n if ('combinator' in node) return evaluateGroup(node, user, now)\n switch (node.kind) {\n case 'user_property':\n return evaluateUserProperty(node, user)\n case 'event_count':\n return evaluateEventCount(node, user)\n case 'event_occurred':\n return evaluateEventOccurred(node, user, now)\n }\n}\n\nfunction evaluateUserProperty(p: UserPropertyPredicate, user: UserState): boolean {\n const actual = user.properties[p.key]\n switch (p.op) {\n case 'exists':\n return actual !== undefined && actual !== null\n case 'not_exists':\n return actual === undefined || actual === null\n case 'eq':\n return actual === p.value\n case 'neq':\n return actual !== p.value\n case 'in':\n return Array.isArray(p.value) && actual != null && (p.value as ReadonlyArray<unknown>).includes(actual)\n case 'nin':\n return Array.isArray(p.value) && actual != null && !(p.value as ReadonlyArray<unknown>).includes(actual)\n case 'gt':\n return typeof actual === 'number' && typeof p.value === 'number' && actual > p.value\n case 'gte':\n return typeof actual === 'number' && typeof p.value === 'number' && actual >= p.value\n case 'lt':\n return typeof actual === 'number' && typeof p.value === 'number' && actual < p.value\n case 'lte':\n return typeof actual === 'number' && typeof p.value === 'number' && actual <= p.value\n case 'contains':\n return typeof actual === 'string' && typeof p.value === 'string' && actual.includes(p.value)\n case 'starts_with':\n return typeof actual === 'string' && typeof p.value === 'string' && actual.startsWith(p.value)\n }\n}\n\nfunction evaluateEventCount(p: EventCountPredicate, user: UserState): boolean {\n const eventBucket = user.eventCounts[p.eventName]\n const count = eventBucket?.[p.windowDays] ?? 0\n switch (p.op) {\n case 'eq': return count === p.count\n case 'gte': return count >= p.count\n case 'lte': return count <= p.count\n case 'gt': return count > p.count\n case 'lt': return count < p.count\n }\n}\n\nfunction evaluateEventOccurred(p: EventOccurredPredicate, user: UserState, now: number): boolean {\n const last = user.lastEventAt[p.eventName]\n if (p.ever) {\n if (!last) return false\n if (p.windowDays == null) return true\n const cutoff = now - p.windowDays * 86400_000\n return Date.parse(last) >= cutoff\n }\n if (!last) return true\n if (p.windowDays == null) return false\n const cutoff = now - p.windowDays * 86400_000\n return Date.parse(last) < cutoff\n}\n\n// ============================================================\n// SerializedSegmentRules → SegmentDsl bridge.\n//\n// The SDK ships armed triggers with a flattened rule set\n// (`SerializedSegmentRules`) for transport efficiency. We deliberately keep\n// only ONE evaluator (`evaluateSegment`) so that server and SDK paths cannot\n// diverge. The bridge converts the serialized form into an AND-combined\n// PredicateGroup and delegates to the same engine.\n// ============================================================\n\nexport function evaluateSerializedSegmentRules(\n rules: SerializedSegmentRules | null | undefined,\n user: UserState,\n now: number = Date.now(),\n): boolean {\n if (!rules) return true\n const dsl = serializedRulesToDsl(rules)\n return evaluateSegment(dsl, user, now)\n}\n\nexport function serializedRulesToDsl(rules: SerializedSegmentRules): SegmentDsl {\n const predicates: Predicate[] = []\n\n for (const rule of rules.userProperties ?? []) {\n predicates.push(userPropertyRuleToPredicate(rule))\n }\n for (const rule of rules.eventCounts ?? []) {\n predicates.push({\n kind: 'event_count',\n eventName: rule.eventName,\n op: rule.op,\n count: rule.count,\n windowDays: rule.windowDays,\n })\n }\n\n return {\n version: 1,\n root: { combinator: 'AND', predicates },\n }\n}\n\nfunction userPropertyRuleToPredicate(rule: UserPropertyRule): UserPropertyPredicate {\n // SerializedSegmentRules constrains operators to a subset; cast safely.\n return {\n kind: 'user_property',\n key: rule.key,\n op: rule.op,\n value: rule.value as UserPropertyPredicate['value'],\n }\n}\n","// ============================================================\n// Branch DSL evaluator — shared by SDKs and dashboard preview.\n// Given a flow, a current question, and the answer just recorded,\n// returns the next question id (or SURVEY_END_SENTINEL).\n// ============================================================\n\nimport {\n SURVEY_END_SENTINEL,\n type SurveyAnswerRecord,\n type SurveyAnswerValue,\n type SurveyBranch,\n type SurveyBranchCondition,\n type SurveyFlow,\n type SurveyQuestion,\n} from '../types/survey.js'\n\nexport function evaluateBranchCondition(\n cond: SurveyBranchCondition,\n answer: SurveyAnswerValue | undefined,\n): boolean {\n if (cond.op === 'answered') return answer !== undefined && answer !== null && answer !== ''\n if (cond.op === 'unanswered') return answer === undefined || answer === null || answer === ''\n if (answer === undefined || answer === null) return false\n\n switch (cond.op) {\n case 'eq':\n return answer === cond.value\n case 'neq':\n return answer !== cond.value\n case 'lt':\n return typeof answer === 'number' && typeof cond.value === 'number' && answer < cond.value\n case 'lte':\n return typeof answer === 'number' && typeof cond.value === 'number' && answer <= cond.value\n case 'gt':\n return typeof answer === 'number' && typeof cond.value === 'number' && answer > cond.value\n case 'gte':\n return typeof answer === 'number' && typeof cond.value === 'number' && answer >= cond.value\n case 'includes':\n return Array.isArray(answer) && (answer as ReadonlyArray<unknown>).includes(cond.value as never)\n case 'not_includes':\n return Array.isArray(answer) && !(answer as ReadonlyArray<unknown>).includes(cond.value as never)\n default:\n return false\n }\n}\n\nexport function nextQuestionId(\n flow: SurveyFlow,\n currentQuestionId: string,\n answers: SurveyAnswerRecord,\n): string | null {\n const branches = flow.branches.filter((b) => b.fromQuestionId === currentQuestionId)\n const answer = answers[currentQuestionId]\n for (const branch of branches) {\n if (evaluateBranchCondition(branch.condition, answer)) {\n if (branch.toQuestionId === SURVEY_END_SENTINEL) return null\n return branch.toQuestionId\n }\n }\n return defaultNext(flow, currentQuestionId)\n}\n\nfunction defaultNext(flow: SurveyFlow, currentQuestionId: string): string | null {\n const idx = flow.questions.findIndex((q) => q.id === currentQuestionId)\n if (idx < 0 || idx >= flow.questions.length - 1) return null\n const next = flow.questions[idx + 1]\n return next ? next.id : null\n}\n\nexport function findQuestion(\n flow: SurveyFlow,\n questionId: string,\n): SurveyQuestion | undefined {\n return flow.questions.find((q) => q.id === questionId)\n}\n\nexport function findQuestionIndex(flow: SurveyFlow, questionId: string): number {\n return flow.questions.findIndex((q) => q.id === questionId)\n}\n\n// Conservative progress estimate: count the current index + 1 over total. Branching\n// makes an exact number impossible, so we expose the worst-case fraction.\nexport function estimateProgress(flow: SurveyFlow, currentQuestionId: string | null): number {\n if (!currentQuestionId) return 1\n const idx = findQuestionIndex(flow, currentQuestionId)\n if (idx < 0) return 0\n return (idx + 1) / Math.max(1, flow.questions.length)\n}\n\n// Given a branch filter list, compute the *reachable* set of questions from a starting\n// point. Used by the composer to render \"dead question\" warnings.\nexport function reachableQuestions(\n flow: SurveyFlow,\n startId?: string,\n): ReadonlySet<string> {\n const start = startId ?? flow.startQuestionId\n const visited = new Set<string>()\n const stack: string[] = [start]\n while (stack.length > 0) {\n const id = stack.pop()\n if (id === undefined) continue\n if (visited.has(id)) continue\n visited.add(id)\n const outgoing = flow.branches.filter((b) => b.fromQuestionId === id)\n for (const b of outgoing) {\n if (b.toQuestionId !== SURVEY_END_SENTINEL) stack.push(b.toQuestionId)\n }\n const idx = flow.questions.findIndex((q) => q.id === id)\n if (idx >= 0 && idx < flow.questions.length - 1) {\n const next = flow.questions[idx + 1]\n if (next) stack.push(next.id)\n }\n }\n return visited\n}\n","import type { PeriodicFrequency } from '../types/campaign.js'\n\nexport interface PeriodicSchedule {\n readonly frequency: PeriodicFrequency\n readonly hourLocal: number\n readonly minuteLocal: number\n /** 0..6 (Sun=0). Required for `weekly`. */\n readonly weekday?: number\n /** 1..31. Required for `monthly`. */\n readonly dayOfMonth?: number\n /** IANA timezone the hour/minute are expressed in. Defaults to UTC. */\n readonly tz?: string\n}\n\n/**\n * Returns the next firing instant (as a Date in UTC) for a structured\n * periodic schedule, strictly after `now`.\n *\n * Pure / dependency-free. Used both server-side (push-scheduler `isDue`\n * check) and client-side (dashboard \"Next occurrence\" preview). Keep\n * deterministic for a given (schedule, now) tuple — no randomness.\n *\n * The walk is bounded — daily 2 iters, weekly 8, monthly 13 — so DST\n * gaps and short-month overflows can't loop forever.\n */\nexport function nextPeriodicFire(\n schedule: PeriodicSchedule,\n now: Date = new Date(),\n): Date {\n const tz = schedule.tz || 'UTC'\n const start = startCandidate(schedule, now, tz)\n return walkForward(start, schedule, now, tz)\n}\n\n/**\n * Minutes east of UTC for `tz` at instant `at`. Falls back to 0 (UTC)\n * for invalid input. Exported so server-side callers can share the\n * same offset math the periodic walker uses (avoids a separate\n * implementation in push-scheduler.ts).\n */\nexport function tzOffsetMinutes(at: Date, tz: string): number {\n if (tz === 'UTC') return 0\n try {\n const fmt = getFormatter(tz)\n const parts = fmt.formatToParts(at).reduce<Record<string, string>>((acc, p) => {\n if (p.type !== 'literal') acc[p.type] = p.value\n return acc\n }, {})\n const utc = Date.UTC(\n Number(parts.year),\n Number(parts.month) - 1,\n Number(parts.day),\n Number(parts.hour) === 24 ? 0 : Number(parts.hour),\n Number(parts.minute),\n Number(parts.second),\n )\n return Math.round((utc - at.getTime()) / 60_000)\n } catch {\n return 0\n }\n}\n\nfunction startCandidate(\n schedule: PeriodicSchedule,\n now: Date,\n tz: string,\n): Date {\n const localNow = wallClock(now, tz)\n const target = new Date(localNow)\n // `wallClock` is an artificial UTC-backed view of the target timezone.\n // Always use UTC accessors so this calculation cannot inherit the host's\n // timezone (the browser for previews, or the server for delivery).\n target.setUTCHours(schedule.hourLocal, schedule.minuteLocal, 0, 0)\n return localToUtc(target, tz)\n}\n\nfunction walkForward(\n candidate: Date,\n schedule: PeriodicSchedule,\n now: Date,\n tz: string,\n): Date {\n let cursor = candidate\n const max = schedule.frequency === 'daily' ? 2 : schedule.frequency === 'weekly' ? 8 : 13\n for (let i = 0; i < max; i++) {\n const local = wallClock(cursor, tz)\n if (matchesFrequency(local, schedule) && cursor.getTime() > now.getTime()) {\n return cursor\n }\n cursor = step(cursor, local, schedule, tz)\n }\n return cursor\n}\n\nfunction matchesFrequency(local: Date, schedule: PeriodicSchedule): boolean {\n if (schedule.frequency === 'daily') return true\n if (schedule.frequency === 'weekly') {\n return schedule.weekday === undefined || local.getUTCDay() === schedule.weekday\n }\n return schedule.dayOfMonth === undefined || local.getUTCDate() === schedule.dayOfMonth\n}\n\nfunction step(\n cursor: Date,\n cursorLocal: Date,\n schedule: PeriodicSchedule,\n tz: string,\n): Date {\n if (schedule.frequency === 'daily' || schedule.frequency === 'weekly') {\n return addDays(cursor, 1)\n }\n // Monthly: jump to the next month at the same dayOfMonth (or last day if shorter).\n const next = new Date(cursorLocal)\n next.setUTCMonth(next.getUTCMonth() + 1)\n if (schedule.dayOfMonth !== undefined) {\n const lastDay = lastDayOfMonth(next.getUTCFullYear(), next.getUTCMonth())\n next.setUTCDate(Math.min(schedule.dayOfMonth, lastDay))\n }\n next.setUTCHours(schedule.hourLocal, schedule.minuteLocal, 0, 0)\n return localToUtc(next, tz)\n}\n\nfunction addDays(d: Date, days: number): Date {\n const next = new Date(d.getTime())\n next.setUTCDate(next.getUTCDate() + days)\n return next\n}\n\nfunction lastDayOfMonth(year: number, monthIndex: number): number {\n return new Date(Date.UTC(year, monthIndex + 1, 0)).getUTCDate()\n}\n\n/** Returns a UTC-backed Date whose `getUTCX()` methods read in `tz`'s wall clock. */\nfunction wallClock(d: Date, tz: string): Date {\n const offsetMin = tzOffsetMinutes(d, tz)\n return new Date(d.getTime() + offsetMin * 60_000)\n}\n\n/** Inverse of `wallClock` — given a Date whose getX reads in `tz`, return UTC. */\nfunction localToUtc(localView: Date, tz: string): Date {\n const offsetMin = tzOffsetMinutes(localView, tz)\n return new Date(localView.getTime() - offsetMin * 60_000)\n}\n\n// `Intl.DateTimeFormat` construction dominates this module's cost (~100 µs\n// per ctor). The scheduler can call `nextPeriodicFire` thousands of times\n// per tick across many users, so we cache one formatter per tz at module\n// scope. Map is keyed by IANA name and lookups are O(1). Safe to share —\n// formatter instances are stateless across calls.\nconst FORMATTER_CACHE = /* @__PURE__ */ new Map<string, Intl.DateTimeFormat>()\n\nfunction getFormatter(tz: string): Intl.DateTimeFormat {\n const cached = FORMATTER_CACHE.get(tz)\n if (cached) return cached\n const fmt = new Intl.DateTimeFormat('en-US', {\n timeZone: tz,\n hour12: false,\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n })\n FORMATTER_CACHE.set(tz, fmt)\n return fmt\n}\n","/** Delivery platform is independent of the customer's integration framework. */\nexport type DeliveryPlatform = 'ios' | 'android' | 'web'\nexport type WebLayout = 'modal' | 'card' | 'panel'\nexport interface WebPresentation {\n readonly layout?: WebLayout\n readonly size?: 'compact' | 'standard' | 'wide'\n readonly position?: 'left' | 'right'\n readonly backdrop?: boolean\n}\nexport interface CampaignDeliveryOptions {\n readonly deliveryPlatforms?: ReadonlyArray<DeliveryPlatform>\n readonly webPresentation?: WebPresentation | null\n}\nexport interface WebAppConfig {\n /** Exact origins, including scheme and non-default port. */\n readonly allowedOrigins: ReadonlyArray<string>\n}\nexport const DELIVERY_PROTOCOL_VERSION = 2 as const\nexport function deliveryPlatformsForApp(platforms: ReadonlyArray<string>): DeliveryPlatform[] {\n const values = new Set<DeliveryPlatform>()\n for (const platform of platforms) {\n if (platform === 'web' || platform === 'ios' || platform === 'android') values.add(platform)\n if (platform === 'expo' || platform === 'react-native' || platform === 'flutter') {\n values.add('ios'); values.add('android')\n }\n }\n return [...values]\n}\nexport function resolveWebPresentation(pillar: 'feedback' | 'survey' | 'inapp' | 'requests', override?: WebPresentation | null) {\n return {\n layout: override?.layout ?? 'modal',\n size: override?.size ?? (pillar === 'requests' ? 'wide' : 'standard'),\n position: override?.position ?? 'right',\n backdrop: override?.backdrop ?? override?.layout !== 'card',\n } as const\n}\n","import { z } from 'zod'\nimport type {\n PersonalizationBinding,\n PersonalizationIssue,\n PersonalizationResolution,\n PersonalizationScalar,\n PersonalizationSourceValue,\n PersonalizationSpec,\n} from './types/personalization.js'\n\nconst id = z.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,63}$/)\nconst key = z\n .string()\n .min(1)\n .max(120)\n .refine(\n (v) => !['__proto__', 'prototype', 'constructor'].includes(v),\n 'Reserved property key',\n )\nconst scalar = z.union([\n z.string().max(8192),\n z.number().finite(),\n z.boolean(),\n z.null(),\n])\nconst baseSource = { id, label: z.string().min(1).max(120) }\nconst filterSchema = z.object({\n key,\n op: z.enum([\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'nin',\n 'contains',\n 'starts_with',\n 'exists',\n 'not_exists',\n ]),\n value: z\n .union([\n z.string(),\n z.number().finite(),\n z.boolean(),\n z.array(z.union([z.string(), z.number().finite()])).max(100),\n ])\n .optional(),\n})\n\nexport const personalizationSpecSchema = z\n .object({\n version: z.literal(1),\n sources: z\n .array(\n z.discriminatedUnion('kind', [\n z.object({ ...baseSource, kind: z.literal('user_property') }),\n z.object({ ...baseSource, kind: z.literal('trigger_event') }),\n z.object({ ...baseSource, kind: z.literal('send_data') }),\n z.object({ ...baseSource, kind: z.literal('app') }),\n z.object({ ...baseSource, kind: z.literal('now') }),\n z.object({\n ...baseSource,\n kind: z.literal('latest_event'),\n eventName: z.string().min(1).max(120),\n lookbackDays: z.number().int().min(1).max(90),\n filters: z.array(filterSchema).max(8).optional(),\n }),\n ]),\n )\n .max(16),\n bindings: z\n .array(\n z.object({\n id,\n label: z.string().min(1).max(120),\n sourceId: id,\n key,\n type: z.enum(['string', 'number', 'boolean', 'date']),\n fallback: scalar.optional(),\n }),\n )\n .max(64),\n missingData: z.literal('skip'),\n })\n .superRefine((spec, ctx) => {\n const sources = new Set(spec.sources.map((source) => source.id))\n if (sources.size !== spec.sources.length)\n ctx.addIssue({\n code: 'custom',\n path: ['sources'],\n message: 'Source IDs must be unique',\n })\n if (\n spec.sources.filter((source) => source.kind === 'latest_event').length > 4\n )\n ctx.addIssue({\n code: 'custom',\n path: ['sources'],\n message: 'Use at most four activity sources',\n })\n const bindings = new Set<string>()\n spec.bindings.forEach((binding, index) => {\n if (bindings.has(binding.id))\n ctx.addIssue({\n code: 'custom',\n path: ['bindings', index, 'id'],\n message: 'Field IDs must be unique',\n })\n bindings.add(binding.id)\n if (!sources.has(binding.sourceId))\n ctx.addIssue({\n code: 'custom',\n path: ['bindings', index, 'sourceId'],\n message: 'Choose an existing source',\n })\n if (\n binding.fallback !== undefined &&\n (isMissing(binding.fallback) ||\n !matchesType(binding.fallback, binding.type))\n )\n ctx.addIssue({\n code: 'custom',\n path: ['bindings', index, 'fallback'],\n message: 'Fallback must be a non-empty value of the selected type',\n })\n })\n })\n\nexport const userPropertiesUpdateSchema = z\n .object({\n mutationId: z.string().uuid(),\n set: z\n .record(key, scalar)\n .refine(\n (v) => Object.keys(v).length <= 64,\n 'Update at most 64 properties',\n )\n .optional(),\n unset: z.array(key).max(64).optional(),\n })\n .superRefine((update, ctx) => {\n if (!Object.keys(update.set ?? {}).length && !update.unset?.length)\n ctx.addIssue({\n code: 'custom',\n message: 'Supply properties to set or remove',\n })\n if (update.unset?.some((name) => Object.hasOwn(update.set ?? {}, name)))\n ctx.addIssue({\n code: 'custom',\n message: 'A property cannot be set and removed in the same update',\n })\n })\n\nfunction isMissing(value: unknown): boolean {\n return value == null || (typeof value === 'string' && !value.trim())\n}\n\nfunction matchesType(\n value: unknown,\n type: PersonalizationBinding['type'],\n): boolean {\n if (type === 'date')\n return typeof value === 'string' && !Number.isNaN(Date.parse(value))\n return (\n typeof value === type &&\n (typeof value !== 'number' || Number.isFinite(value))\n )\n}\n\nexport function resolvePersonalizationBindings(\n spec: PersonalizationSpec,\n sources: Readonly<Record<string, PersonalizationSourceValue>>,\n): PersonalizationResolution {\n const values: Record<string, PersonalizationScalar> = Object.create(null)\n const issues: PersonalizationIssue[] = []\n const fallbackBindingIds: string[] = []\n for (const binding of spec.bindings) {\n const source = sources[binding.sourceId]?.values\n const value =\n source && Object.hasOwn(source, binding.key)\n ? source[binding.key]\n : undefined\n const missing = isMissing(value)\n if (!missing && matchesType(value, binding.type))\n values[binding.id] = value!\n else if (missing && binding.fallback !== undefined) {\n values[binding.id] = binding.fallback\n fallbackBindingIds.push(binding.id)\n } else\n issues.push({\n code: missing ? 'missing' : 'type_mismatch',\n bindingId: binding.id,\n message: missing\n ? `${binding.label} is missing`\n : `${binding.label} must be ${binding.type}`,\n })\n }\n return {\n status: issues.length\n ? 'skipped'\n : fallbackBindingIds.length\n ? 'using_fallback'\n : 'ready',\n values,\n fallbackBindingIds,\n issues,\n sources,\n }\n}\n\nconst TOKEN = /\\{\\{\\s*p\\.([A-Za-z][A-Za-z0-9_]*)\\s*\\}\\}/g\nconst WHOLE_TOKEN = /^\\{\\{\\s*p\\.([A-Za-z][A-Za-z0-9_]*)\\s*\\}\\}$/\n\nexport function personalizationToken(bindingId: string): string {\n return `{{p.${bindingId}}}`\n}\n\n/** Resolve only explicit template values. JSON keys and substituted values are never evaluated. */\nexport function renderPersonalizedValue(\n input: unknown,\n values: Readonly<Record<string, PersonalizationScalar>>,\n issues: PersonalizationIssue[],\n path = '',\n mode: 'text' | 'json' | 'url' = 'text',\n): unknown {\n if (typeof input === 'string') {\n const whole = WHOLE_TOKEN.exec(input)\n const lookup = (bindingId: string): PersonalizationScalar => {\n if (Object.hasOwn(values, bindingId)) return values[bindingId]!\n issues.push({\n code: 'unknown_binding',\n bindingId,\n path,\n message: `No value is available for ${bindingId}`,\n })\n return null\n }\n if (mode === 'json' && whole) return lookup(whole[1]!)\n // Inspect the template before replacing: a supplied value may legitimately contain braces.\n if (/\\{\\{|\\}\\}/.test(input.replace(TOKEN, '')))\n issues.push({\n code: 'invalid_template',\n path,\n message: 'Insert a valid dynamic field',\n })\n const result = input.replace(TOKEN, (_, bindingId: string) => {\n const value = lookup(bindingId)\n return mode === 'url' && !whole\n ? encodeURIComponent(String(value ?? ''))\n : String(value ?? '')\n })\n if (mode === 'url' && result) {\n try {\n const url = new URL(result)\n if (\n ['javascript:', 'data:', 'file:', 'vbscript:'].includes(url.protocol)\n )\n throw new Error('unsafe')\n // The origin/scheme must be static unless the entire field is a URL binding.\n if (!whole && /\\{\\{/.test(input.split(/:\\/\\//)[0] ?? ''))\n throw new Error('dynamic scheme')\n if (\n !whole &&\n /\\{\\{/.test(\n input.match(/^[a-z][a-z0-9+.-]*:\\/\\/([^/?#]*)/i)?.[1] ?? '',\n )\n )\n throw new Error('dynamic authority')\n } catch {\n issues.push({\n code: 'invalid_destination',\n path,\n message:\n 'The resolved destination must be a valid app link or web URL',\n })\n }\n }\n return result\n }\n if (Array.isArray(input))\n return input.map((item, index) =>\n renderPersonalizedValue(item, values, issues, `${path}/${index}`, mode),\n )\n if (input && typeof input === 'object') {\n const result: Record<string, unknown> = Object.create(null)\n for (const [name, value] of Object.entries(input)) {\n if (['__proto__', 'constructor', 'prototype'].includes(name)) {\n issues.push({\n code: 'invalid_template',\n path,\n message: 'Reserved object key',\n })\n continue\n }\n result[name] = renderPersonalizedValue(\n value,\n values,\n issues,\n `${path}/${name}`,\n mode,\n )\n }\n return result\n }\n return input\n}\n\n/** Display-only keys: identifiers, scores, branching and targeting are always kept verbatim. */\nconst TEXT_KEYS = new Set([\n 'title',\n 'body',\n 'subtitle',\n 'headline',\n 'label',\n 'placeholder',\n 'followUp',\n 'lowLabel',\n 'highLabel',\n 'description',\n 'buttonText',\n 'submitLabel',\n 'nextLabel',\n 'backLabel',\n 'text',\n])\nconst URL_KEYS = new Set(['imageUrl', 'deepLink', 'target'])\nconst CONTENT_KEYS = new Set([\n 'questions',\n 'options',\n 'ctas',\n 'cta',\n 'actionButtons',\n 'flow',\n 'welcome',\n 'thankYou',\n 'completion',\n 'endScreen',\n 'openAction',\n])\n\n/** Records where a field is used, excluding campaign metadata and targeting. */\nexport function personalizationUsage(\n content: unknown,\n): Map<string, Set<string>> {\n const usage = new Map<string, Set<string>>()\n const scan = (value: unknown, field: string) => {\n if (typeof value === 'string') {\n for (const match of value.matchAll(TOKEN)) {\n const fields = usage.get(match[1]!) ?? new Set<string>()\n fields.add(field)\n usage.set(match[1]!, fields)\n }\n } else if (Array.isArray(value)) value.forEach((item) => scan(item, field))\n else if (value && typeof value === 'object')\n Object.values(value).forEach((item) => scan(item, field))\n }\n const walk = (value: unknown) => {\n if (Array.isArray(value)) {\n value.forEach(walk)\n return\n }\n if (!value || typeof value !== 'object') return\n for (const [key, item] of Object.entries(value)) {\n if (\n TEXT_KEYS.has(key) ||\n URL_KEYS.has(key) ||\n key === 'actionJson' ||\n key === 'payloadExtras'\n )\n scan(item, key)\n else if (CONTENT_KEYS.has(key)) walk(item)\n }\n }\n walk(content)\n return usage\n}\n\nexport function renderPersonalizedContent<T>(\n content: T,\n resolution: PersonalizationResolution,\n): {\n content: T\n resolution: PersonalizationResolution\n} {\n const usage = personalizationUsage(content)\n const onlyOptionalImage = (id: string) =>\n usage.get(id)?.size === 1 && usage.get(id)?.has('imageUrl')\n const issues = resolution.issues.filter(\n (issue) =>\n !issue.bindingId ||\n (usage.has(issue.bindingId) &&\n !(issue.code === 'missing' && onlyOptionalImage(issue.bindingId))),\n )\n const fallbacks = resolution.fallbackBindingIds.filter((id) => usage.has(id))\n const walk = (value: unknown, path = ''): unknown => {\n if (Array.isArray(value))\n return value.map((item, index) => walk(item, `${path}/${index}`))\n if (!value || typeof value !== 'object') return value\n return Object.fromEntries(\n Object.entries(value).map(([name, item]) => {\n const childPath = `${path}/${name}`\n if (TEXT_KEYS.has(name) && typeof item === 'string')\n return [\n name,\n renderPersonalizedValue(item, resolution.values, issues, childPath),\n ]\n if (URL_KEYS.has(name) && typeof item === 'string') {\n if (\n name === 'imageUrl' &&\n [...item.matchAll(TOKEN)].some((match) =>\n resolution.issues.some(\n (issue) =>\n issue.bindingId === match[1] && issue.code === 'missing',\n ),\n )\n )\n return [name, null]\n // custom_event targets are event identifiers, not destinations.\n const isEvent =\n name === 'target' &&\n (value as { action?: string }).action === 'custom_event'\n const rendered = renderPersonalizedValue(\n item,\n resolution.values,\n issues,\n childPath,\n isEvent ? 'text' : 'url',\n )\n if (\n name === 'imageUrl' &&\n rendered &&\n !String(rendered).startsWith('https://')\n )\n issues.push({\n code: 'invalid_destination',\n path: childPath,\n message: 'Image URLs must use HTTPS',\n })\n return [name, rendered]\n }\n if (name === 'actionJson' || name === 'payloadExtras')\n return [\n name,\n renderPersonalizedValue(\n item,\n resolution.values,\n issues,\n childPath,\n 'json',\n ),\n ]\n if (CONTENT_KEYS.has(name)) return [name, walk(item, childPath)]\n return [name, item]\n }),\n )\n }\n const rendered = walk(content) as T\n return {\n content: rendered,\n resolution: {\n ...resolution,\n fallbackBindingIds: fallbacks,\n status: issues.length\n ? 'skipped'\n : fallbacks.length\n ? 'using_fallback'\n : 'ready',\n issues,\n },\n }\n}\n","/** Runtime-only readiness state. Pausing never stops analytics or dismisses active UI. */\nexport class PresentationGate {\n private paused: boolean\n private identity = 0\n private revisions = { feedback: 0, survey: 0 }\n private readonly listeners = new Set<() => void>()\n\n constructor(paused = false) { this.paused = paused }\n get isPaused(): boolean { return this.paused }\n setPaused(paused: boolean): void {\n this.paused = paused\n this.notify()\n }\n invalidate(purpose?: 'feedback' | 'survey'): void {\n if (purpose) this.revisions[purpose]++\n else this.identity++\n this.notify()\n }\n validator(purpose: 'feedback' | 'survey'): () => boolean {\n const identity = this.identity\n const revision = this.revisions[purpose]\n return () => identity === this.identity && revision === this.revisions[purpose]\n }\n subscribe(listener: () => void): () => void {\n this.listeners.add(listener)\n return () => { this.listeners.delete(listener) }\n }\n runWhenReady(run: () => void, valid: () => boolean, cancel: () => void = () => {}): void {\n if (!valid()) { cancel(); return }\n if (!this.paused) { run(); return }\n const stop = this.subscribe(() => {\n if (valid() && this.paused) return\n stop()\n if (valid()) run()\n else cancel()\n })\n }\n waitUntilReady(valid: () => boolean): Promise<boolean> {\n if (!valid()) return Promise.resolve(false)\n if (!this.paused) return Promise.resolve(true)\n return new Promise((resolve) => {\n const stop = this.subscribe(() => {\n if (valid() && this.paused) return\n stop()\n resolve(valid())\n })\n })\n }\n private notify(): void {\n for (const listener of [...this.listeners]) listener()\n }\n}\n"]}