@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.
package/dist/index.js CHANGED
@@ -25,6 +25,16 @@ function err(code, message, details) {
25
25
  };
26
26
  }
27
27
 
28
+ // src/types/workspace.ts
29
+ function defaultOnboardingMessage(appName) {
30
+ return {
31
+ title: `Welcome to ${appName.trim() || "our app"}`,
32
+ body: "Glad you\u2019re here. Take a look around and make yourself at home.",
33
+ buttonLabel: "Got it",
34
+ format: "modal"
35
+ };
36
+ }
37
+
28
38
  // src/types/survey.ts
29
39
  var SURVEY_END_SENTINEL = "__end__";
30
40
 
@@ -268,8 +278,8 @@ var THEME_PRESETS = [
268
278
  swatches: ["#8B5CF6", "#EC4899", "#E9D5FF"]
269
279
  }
270
280
  ];
271
- function getThemePresetById(id) {
272
- return THEME_PRESETS.find((preset) => preset.id === id);
281
+ function getThemePresetById(id2) {
282
+ return THEME_PRESETS.find((preset) => preset.id === id2);
273
283
  }
274
284
  function defaultThemePreset() {
275
285
  return THEME_PRESETS[0];
@@ -320,7 +330,7 @@ var USER_IDENTIFIED_EVENT_NAME = "$user_identified";
320
330
  function camelize(value) {
321
331
  return value.replace(/_([a-z])/g, (_match, letter) => letter.toUpperCase());
322
332
  }
323
- var ids = (...keys) => Object.fromEntries(keys.map((key) => [key, [key, camelize(key)]]));
333
+ var ids = (...keys) => Object.fromEntries(keys.map((key2) => [key2, [key2, camelize(key2)]]));
324
334
  var pushEvents = [
325
335
  ["$push_sent", "UserGist Push Sent"],
326
336
  ["$push_delivered", "UserGist Push Delivered"],
@@ -377,8 +387,8 @@ var CORE_INTEGRATION_EVENTS = [
377
387
  { key: "$inapp_dismissed", name: "UserGist In-App Message Dismissed", category: "inapp", subjectRole: "actor", properties: { ...ids("message_id", "dismiss_reason") } },
378
388
  { key: "$inapp_auto_dismissed", name: "UserGist In-App Message Auto-Dismissed", category: "inapp", subjectRole: "actor", properties: { ...ids("message_id", "dismiss_reason") } },
379
389
  { 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"] } },
380
- ...pushEvents.map(([key, name]) => ({
381
- key,
390
+ ...pushEvents.map(([key2, name]) => ({
391
+ key: key2,
382
392
  name,
383
393
  category: "push",
384
394
  subjectRole: "actor",
@@ -387,11 +397,11 @@ var CORE_INTEGRATION_EVENTS = [
387
397
  action_id: ["action_id", "actionId", "action_button", "actionButton"]
388
398
  }
389
399
  })),
390
- ...requestEvents.map(([key, name, subjectRole]) => ({ key, name, category: "requests", subjectRole, properties: { ...ids("request_id", "comment_id", "source", "old_status", "new_status", "deleted_by"), usergist_actor_type: ["usergist_actor_type", "actor_type"] } }))
400
+ ...requestEvents.map(([key2, name, subjectRole]) => ({ key: key2, name, category: "requests", subjectRole, properties: { ...ids("request_id", "comment_id", "source", "old_status", "new_status", "deleted_by"), usergist_actor_type: ["usergist_actor_type", "actor_type"] } }))
391
401
  ];
392
402
  var CORE_EVENT_BY_KEY = new Map(CORE_INTEGRATION_EVENTS.map((event) => [event.key, event]));
393
- function getCoreIntegrationEvent(key) {
394
- return CORE_EVENT_BY_KEY.get(key) ?? null;
403
+ function getCoreIntegrationEvent(key2) {
404
+ return CORE_EVENT_BY_KEY.get(key2) ?? null;
395
405
  }
396
406
  function sanitizeCoreIntegrationProperties(definition, input) {
397
407
  if (!input) return {};
@@ -498,15 +508,15 @@ function evaluateGroup(group, user, now) {
498
508
  }
499
509
  return group.predicates.some((p) => evaluateNode(p, user, now));
500
510
  }
501
- function evaluateNode(node, user, now) {
502
- if ("combinator" in node) return evaluateGroup(node, user, now);
503
- switch (node.kind) {
511
+ function evaluateNode(node2, user, now) {
512
+ if ("combinator" in node2) return evaluateGroup(node2, user, now);
513
+ switch (node2.kind) {
504
514
  case "user_property":
505
- return evaluateUserProperty(node, user);
515
+ return evaluateUserProperty(node2, user);
506
516
  case "event_count":
507
- return evaluateEventCount(node, user);
517
+ return evaluateEventCount(node2, user);
508
518
  case "event_occurred":
509
- return evaluateEventOccurred(node, user, now);
519
+ return evaluateEventOccurred(node2, user, now);
510
520
  }
511
521
  }
512
522
  function evaluateUserProperty(p, user) {
@@ -660,15 +670,15 @@ function reachableQuestions(flow, startId) {
660
670
  const visited = /* @__PURE__ */ new Set();
661
671
  const stack = [start];
662
672
  while (stack.length > 0) {
663
- const id = stack.pop();
664
- if (id === void 0) continue;
665
- if (visited.has(id)) continue;
666
- visited.add(id);
667
- const outgoing = flow.branches.filter((b) => b.fromQuestionId === id);
673
+ const id2 = stack.pop();
674
+ if (id2 === void 0) continue;
675
+ if (visited.has(id2)) continue;
676
+ visited.add(id2);
677
+ const outgoing = flow.branches.filter((b) => b.fromQuestionId === id2);
668
678
  for (const b of outgoing) {
669
679
  if (b.toQuestionId !== SURVEY_END_SENTINEL) stack.push(b.toQuestionId);
670
680
  }
671
- const idx = flow.questions.findIndex((q) => q.id === id);
681
+ const idx = flow.questions.findIndex((q) => q.id === id2);
672
682
  if (idx >= 0 && idx < flow.questions.length - 1) {
673
683
  const next = flow.questions[idx + 1];
674
684
  if (next) stack.push(next.id);
@@ -707,7 +717,7 @@ function tzOffsetMinutes(at, tz) {
707
717
  function startCandidate(schedule, now, tz) {
708
718
  const localNow = wallClock(now, tz);
709
719
  const target = new Date(localNow);
710
- target.setHours(schedule.hourLocal, schedule.minuteLocal, 0, 0);
720
+ target.setUTCHours(schedule.hourLocal, schedule.minuteLocal, 0, 0);
711
721
  return localToUtc(target, tz);
712
722
  }
713
723
  function walkForward(candidate, schedule, now, tz) {
@@ -725,30 +735,30 @@ function walkForward(candidate, schedule, now, tz) {
725
735
  function matchesFrequency(local, schedule) {
726
736
  if (schedule.frequency === "daily") return true;
727
737
  if (schedule.frequency === "weekly") {
728
- return schedule.weekday === void 0 || local.getDay() === schedule.weekday;
738
+ return schedule.weekday === void 0 || local.getUTCDay() === schedule.weekday;
729
739
  }
730
- return schedule.dayOfMonth === void 0 || local.getDate() === schedule.dayOfMonth;
740
+ return schedule.dayOfMonth === void 0 || local.getUTCDate() === schedule.dayOfMonth;
731
741
  }
732
742
  function step(cursor, cursorLocal, schedule, tz) {
733
743
  if (schedule.frequency === "daily" || schedule.frequency === "weekly") {
734
744
  return addDays(cursor, 1);
735
745
  }
736
746
  const next = new Date(cursorLocal);
737
- next.setMonth(next.getMonth() + 1);
747
+ next.setUTCMonth(next.getUTCMonth() + 1);
738
748
  if (schedule.dayOfMonth !== void 0) {
739
- const lastDay = lastDayOfMonth(next.getFullYear(), next.getMonth());
740
- next.setDate(Math.min(schedule.dayOfMonth, lastDay));
749
+ const lastDay = lastDayOfMonth(next.getUTCFullYear(), next.getUTCMonth());
750
+ next.setUTCDate(Math.min(schedule.dayOfMonth, lastDay));
741
751
  }
742
- next.setHours(schedule.hourLocal, schedule.minuteLocal, 0, 0);
752
+ next.setUTCHours(schedule.hourLocal, schedule.minuteLocal, 0, 0);
743
753
  return localToUtc(next, tz);
744
754
  }
745
755
  function addDays(d, days) {
746
756
  const next = new Date(d.getTime());
747
- next.setDate(next.getDate() + days);
757
+ next.setUTCDate(next.getUTCDate() + days);
748
758
  return next;
749
759
  }
750
760
  function lastDayOfMonth(year, monthIndex) {
751
- return new Date(year, monthIndex + 1, 0).getDate();
761
+ return new Date(Date.UTC(year, monthIndex + 1, 0)).getUTCDate();
752
762
  }
753
763
  function wallClock(d, tz) {
754
764
  const offsetMin = tzOffsetMinutes(d, tz);
@@ -776,11 +786,151 @@ function getFormatter(tz) {
776
786
  return fmt;
777
787
  }
778
788
 
789
+ // src/timezone.ts
790
+ var PARTS_FORMATTER_CACHE = /* @__PURE__ */ new Map();
791
+ function isValidIanaTimeZone(value) {
792
+ if (!value.trim()) return false;
793
+ try {
794
+ new Intl.DateTimeFormat("en-US", { timeZone: value }).format();
795
+ return true;
796
+ } catch {
797
+ return false;
798
+ }
799
+ }
800
+ function zonedDateTimeParts(instant, timeZone) {
801
+ if (!isValidIanaTimeZone(timeZone)) {
802
+ throw new RangeError(`Invalid IANA timezone: ${timeZone}`);
803
+ }
804
+ if (!Number.isFinite(instant.getTime())) {
805
+ throw new RangeError("Invalid date");
806
+ }
807
+ const formatter = getPartsFormatter(timeZone);
808
+ const parts = formatter.formatToParts(instant).reduce(
809
+ (result, part) => {
810
+ if (part.type !== "literal") result[part.type] = part.value;
811
+ return result;
812
+ },
813
+ {}
814
+ );
815
+ const year = Number(parts.year);
816
+ const month = Number(parts.month);
817
+ const day = Number(parts.day);
818
+ const hour = Number(parts.hour);
819
+ const minute = Number(parts.minute);
820
+ return {
821
+ date: `${year}-${pad2(month)}-${pad2(day)}`,
822
+ time: `${pad2(hour)}:${pad2(minute)}`,
823
+ weekday: new Date(Date.UTC(year, month - 1, day)).getUTCDay(),
824
+ dayOfMonth: day
825
+ };
826
+ }
827
+ function zonedDateTimeToUtc(date, time, timeZone) {
828
+ if (!isValidIanaTimeZone(timeZone)) {
829
+ throw new RangeError(`Invalid IANA timezone: ${timeZone}`);
830
+ }
831
+ const dateMatch = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date);
832
+ const timeMatch = /^(\d{2}):(\d{2})$/.exec(time);
833
+ if (!dateMatch || !timeMatch) throw new RangeError("Invalid local date or time");
834
+ const year = Number(dateMatch[1]);
835
+ const month = Number(dateMatch[2]);
836
+ const day = Number(dateMatch[3]);
837
+ const hour = Number(timeMatch[1]);
838
+ const minute = Number(timeMatch[2]);
839
+ const naive = Date.UTC(year, month - 1, day, hour, minute, 0, 0);
840
+ const calendarCheck = new Date(naive);
841
+ if (calendarCheck.getUTCFullYear() !== year || calendarCheck.getUTCMonth() !== month - 1 || calendarCheck.getUTCDate() !== day || hour > 23 || minute > 59) {
842
+ throw new RangeError("Invalid local date or time");
843
+ }
844
+ const offsets = new Set(
845
+ [-36, -12, 0, 12, 36].map(
846
+ (hours) => timeZoneOffsetMinutes(new Date(naive + hours * 36e5), timeZone)
847
+ )
848
+ );
849
+ const candidates = [...offsets].map((offset) => new Date(naive - offset * 6e4)).filter((candidate2) => {
850
+ const roundTrip = zonedDateTimeParts(candidate2, timeZone);
851
+ return roundTrip.date === date && roundTrip.time === time;
852
+ }).sort((left, right) => left.getTime() - right.getTime());
853
+ const candidate = candidates[0];
854
+ if (!candidate) {
855
+ throw new RangeError("This local time does not exist in the selected timezone");
856
+ }
857
+ return candidate;
858
+ }
859
+ function zonedDateEndToUtc(date, timeZone) {
860
+ const lastMinute = zonedDateTimeToUtc(date, "23:59", timeZone);
861
+ return new Date(lastMinute.getTime() + 59999);
862
+ }
863
+ function timeZoneOffsetMinutes(instant, timeZone) {
864
+ const parts = getPartsFormatter(timeZone).formatToParts(instant).reduce((result, part) => {
865
+ if (part.type !== "literal") result[part.type] = part.value;
866
+ return result;
867
+ }, {});
868
+ const asUtc = Date.UTC(
869
+ Number(parts.year),
870
+ Number(parts.month) - 1,
871
+ Number(parts.day),
872
+ Number(parts.hour),
873
+ Number(parts.minute),
874
+ Number(parts.second)
875
+ );
876
+ return Math.round((asUtc - instant.getTime()) / 6e4);
877
+ }
878
+ function getPartsFormatter(timeZone) {
879
+ const cached = PARTS_FORMATTER_CACHE.get(timeZone);
880
+ if (cached) return cached;
881
+ const formatter = new Intl.DateTimeFormat("en-US", {
882
+ timeZone,
883
+ hourCycle: "h23",
884
+ year: "numeric",
885
+ month: "2-digit",
886
+ day: "2-digit",
887
+ hour: "2-digit",
888
+ minute: "2-digit",
889
+ second: "2-digit"
890
+ });
891
+ PARTS_FORMATTER_CACHE.set(timeZone, formatter);
892
+ return formatter;
893
+ }
894
+ function pad2(value) {
895
+ return String(value).padStart(2, "0");
896
+ }
897
+
779
898
  // src/contract/endpoints.ts
780
899
  var endpoints = {
900
+ "GET /v1/apps/:appId/search": {},
901
+ "POST /v1/apps/:appId/delivery-diagnostics": {},
902
+ "GET /v1/workspaces/:wid/portal": {},
903
+ "PUT /v1/workspaces/:wid/portal": {},
904
+ "GET /v1/workspaces/:wid/portal/slug-available": {},
905
+ "PUT /v1/workspaces/:wid/portal/apps/:appId": {},
906
+ "POST /v1/workspaces/:wid/portal/publish": {},
907
+ "POST /v1/workspaces/:wid/portal/unpublish": {},
908
+ "GET /v1/workspaces/:wid/portal/preview/:appId": {},
909
+ "PATCH /v1/apps/:appId/requests/portal-visibility": {},
910
+ "GET /v1/portal/:portalSlug": {},
911
+ "GET /v1/portal/:portalSlug/apps/:appSlug/requests": {},
912
+ "GET /v1/portal/:portalSlug/apps/:appSlug/requests/counts": {},
913
+ "GET /v1/portal/:portalSlug/apps/:appSlug/requests/:requestId": {},
914
+ "POST /v1/portal/:portalSlug/auth/start": {},
915
+ "POST /v1/portal/:portalSlug/auth/verify": {},
916
+ "GET /v1/portal/:portalSlug/session": {},
917
+ "DELETE /v1/portal/:portalSlug/session": {},
918
+ "GET /v1/portal/:portalSlug/apps/:appSlug/votes": {},
919
+ "POST /v1/portal/:portalSlug/apps/:appSlug/requests": {},
920
+ "PUT /v1/portal/:portalSlug/apps/:appSlug/requests/:requestId/vote": {},
921
+ "POST /v1/sdk/clients": {},
922
+ "POST /v1/sdk/clients/:id/end": {},
923
+ "GET /v1/sdk/clients/:id/instructions": {},
924
+ "POST /v1/sdk/presentations/authorize": {},
925
+ "POST /v1/sdk/presentations/:id/receipt": {},
781
926
  "GET /v1/me": {},
927
+ "PATCH /v1/me": {},
928
+ "PATCH /v1/me/onboarding": {},
929
+ "GET /v1/features": {},
930
+ "GET /v1/signup-status": {},
782
931
  "GET /v1/workspaces": {},
783
932
  "POST /v1/workspaces": {},
933
+ "PATCH /v1/workspaces/:wid": {},
784
934
  "GET /v1/workspaces/:wid/members": {},
785
935
  "GET /v1/workspaces/:wid/invites": {},
786
936
  "POST /v1/workspaces/:wid/invites": {},
@@ -789,11 +939,18 @@ var endpoints = {
789
939
  "GET /v1/workspaces/:wid/apps": {},
790
940
  "POST /v1/workspaces/:wid/apps": {},
791
941
  "GET /v1/workspaces/:wid/api-tokens": {},
942
+ "GET /v1/workspaces/:wid/ai-connections": {},
943
+ "PATCH /v1/workspaces/:wid/ai-connections/:id": {},
944
+ "POST /v1/workspaces/:wid/ai-connections/:id/revoke": {},
945
+ "GET /v1/workspaces/:wid/ai-connections/:id/activity": {},
946
+ "POST /v1/mcp/consent": {},
792
947
  "POST /v1/workspaces/:wid/api-tokens": {},
793
948
  "DELETE /v1/workspaces/:wid/api-tokens/:tokenId": {},
794
949
  "GET /v1/apps/:appId": {},
795
950
  "PATCH /v1/apps/:appId": {},
796
951
  "DELETE /v1/apps/:appId": {},
952
+ "GET /v1/apps/:appId/onboarding": {},
953
+ "PATCH /v1/apps/:appId/onboarding": {},
797
954
  "POST /v1/apps/:appId/sdk/subject-tokens": {},
798
955
  // ---------- outbound analytics integrations ----------
799
956
  "GET /v1/apps/:appId/integrations": {},
@@ -850,6 +1007,10 @@ var endpoints = {
850
1007
  "POST /v1/sdk/ingest": {},
851
1008
  "GET /v1/sdk/armed-triggers": {},
852
1009
  "POST /v1/sdk/consent": {},
1010
+ "PATCH /v1/apps/:appId/users/properties": {},
1011
+ "POST /v1/sdk/user-properties": {},
1012
+ "GET /v1/apps/:appId/personalization/fields": {},
1013
+ "POST /v1/apps/:appId/personalization/preview": {},
853
1014
  "POST /v1/sdk/identify": {},
854
1015
  "POST /v1/sdk/responses": {},
855
1016
  // GDPR
@@ -954,6 +1115,9 @@ var endpoints = {
954
1115
  "GET /v1/apps/:appId/request-settings": {},
955
1116
  "PUT /v1/apps/:appId/request-settings": {},
956
1117
  "GET /v1/apps/:appId/request-settings/slug-available": {},
1118
+ /** Multipart `file` field; the processed logo URL is saved into branding.logoUrl. */
1119
+ "POST /v1/apps/:appId/request-settings/logo": {},
1120
+ "DELETE /v1/apps/:appId/request-settings/logo": {},
957
1121
  "POST /v1/apps/:appId/requests/seed-segments": {},
958
1122
  // ---------- feature requests — SDK (write-key) ----------
959
1123
  "GET /v1/sdk/requests": {},
@@ -981,8 +1145,15 @@ var endpoints = {
981
1145
  "GET /v1/workspaces/:wid/billing/periods": {},
982
1146
  // ---------- super admin ----------
983
1147
  "GET /v1/admin/session": {},
1148
+ "GET /v1/admin/feature-flags": {},
1149
+ "PATCH /v1/admin/feature-flags/:key": {},
984
1150
  "GET /v1/admin/customers": {},
985
1151
  "GET /v1/admin/customers/:workspaceId": {},
1152
+ "POST /v1/admin/customers/:workspaceId/permanent-deletion": {},
1153
+ "GET /v1/admin/dashboard-users": {},
1154
+ "POST /v1/admin/dashboard-users/:userId/permanent-deletion": {},
1155
+ "GET /v1/admin/deletion-jobs/:jobId": {},
1156
+ "POST /v1/admin/deletion-jobs/:jobId/retry": {},
986
1157
  "POST /v1/admin/customers/:workspaceId/billing-events/:eventId/replay": {},
987
1158
  "POST /v1/admin/customers/:workspaceId/grants": {},
988
1159
  "POST /v1/admin/customers/:workspaceId/grants/:grantId/extend": {},
@@ -995,7 +1166,43 @@ var endpoints = {
995
1166
  // ---------- feature requests — public web roadmap (no auth) ----------
996
1167
  "GET /v1/public/roadmap/:slug": {},
997
1168
  "GET /v1/public/roadmap/:slug/r/:requestId": {},
998
- "GET /v1/public/roadmap/:slug/branding": {}
1169
+ "GET /v1/public/roadmap/:slug/branding": {},
1170
+ "GET /v1/apps/:appId/help/articles": {},
1171
+ "POST /v1/apps/:appId/help/articles": {},
1172
+ "GET /v1/apps/:appId/help/articles/:documentId": {},
1173
+ "PUT /v1/apps/:appId/help/articles/:documentId": {},
1174
+ "POST /v1/apps/:appId/help/articles/:documentId/lifecycle": {},
1175
+ "GET /v1/apps/:appId/changelog": {},
1176
+ "POST /v1/apps/:appId/changelog": {},
1177
+ "GET /v1/apps/:appId/changelog/:documentId": {},
1178
+ "PUT /v1/apps/:appId/changelog/:documentId": {},
1179
+ "POST /v1/apps/:appId/changelog/:documentId/lifecycle": {},
1180
+ "GET /v1/apps/:appId/help/collections": {},
1181
+ "POST /v1/apps/:appId/help/collections": {},
1182
+ "PATCH /v1/apps/:appId/help/collections/:collectionId": {},
1183
+ "POST /v1/apps/:appId/help/collections/:collectionId/position": {},
1184
+ "POST /v1/apps/:appId/help/articles/:documentId/position": {},
1185
+ "GET /v1/apps/:appId/roadmap": {},
1186
+ "POST /v1/apps/:appId/roadmap": {},
1187
+ "GET /v1/apps/:appId/roadmap/:itemId": {},
1188
+ "PUT /v1/apps/:appId/roadmap/:itemId": {},
1189
+ "POST /v1/apps/:appId/roadmap/:itemId/status": {},
1190
+ "POST /v1/apps/:appId/roadmap/:itemId/lifecycle": {},
1191
+ "GET /v1/portal/:portalSlug/apps/:appSlug/help/collections": {},
1192
+ "GET /v1/portal/:portalSlug/apps/:appSlug/help/collections/:collectionId": {},
1193
+ "GET /v1/portal/:portalSlug/apps/:appSlug/help/articles": {},
1194
+ "GET /v1/portal/:portalSlug/apps/:appSlug/help/articles/:documentId": {},
1195
+ "GET /v1/portal/:portalSlug/apps/:appSlug/changelog": {},
1196
+ "GET /v1/portal/:portalSlug/apps/:appSlug/changelog/:documentId": {},
1197
+ "GET /v1/portal/:portalSlug/apps/:appSlug/roadmap": {},
1198
+ "GET /v1/portal/:portalSlug/apps/:appSlug/roadmap/:itemId": {},
1199
+ "GET /v1/portal/:portalSlug/apps/:appSlug/requests/:requestId/changelog": {},
1200
+ "GET /v1/portal/:portalSlug/apps/:appSlug/roadmap/:itemId/changelog": {},
1201
+ "GET /v1/apps/:appId/portal-content/link-targets": {},
1202
+ // Binary routes use multipart/stream transports, not the JSON client helper.
1203
+ "POST /v1/apps/:appId/portal-content/assets/:kind/:documentId": {},
1204
+ "GET /v1/apps/:appId/portal-content/assets/:assetId": {},
1205
+ "GET /v1/portal/:portalSlug/apps/:appSlug/assets/:assetId": {}
999
1206
  };
1000
1207
 
1001
1208
  // src/schemas/index.ts
@@ -1003,24 +1210,74 @@ var schemas_exports = {};
1003
1210
  __export(schemas_exports, {
1004
1211
  acceptWorkspaceInviteSchema: () => acceptWorkspaceInviteSchema,
1005
1212
  apiTokenScopeSchema: () => apiTokenScopeSchema,
1213
+ contentActionSchema: () => contentActionSchema,
1214
+ contentBodySchema: () => contentBodySchema,
1215
+ contentKindSchema: () => contentKindSchema,
1216
+ contentLinkQuerySchema: () => contentLinkQuerySchema,
1217
+ contentLinkSchema: () => contentLinkSchema,
1218
+ contentPageQuerySchema: () => contentPageQuerySchema,
1219
+ contentQuerySchema: () => contentQuerySchema,
1220
+ contentStateSchema: () => contentStateSchema,
1006
1221
  createApiTokenSchema: () => createApiTokenSchema,
1007
1222
  createAppSchema: () => createAppSchema,
1223
+ createCollectionSchema: () => createCollectionSchema,
1224
+ createDocumentSchema: () => createDocumentSchema,
1225
+ createRoadmapSchema: () => createRoadmapSchema,
1008
1226
  createWorkspaceSchema: () => createWorkspaceSchema,
1009
1227
  createWriteKeySchema: () => createWriteKeySchema,
1228
+ deferCurrentUserOnboardingSchema: () => deferCurrentUserOnboardingSchema,
1229
+ deliveryPlatformsSchema: () => deliveryPlatformsSchema,
1230
+ documentDraftSchema: () => documentDraftSchema,
1010
1231
  emailSchema: () => emailSchema,
1011
1232
  inviteMemberSchema: () => inviteMemberSchema,
1012
1233
  isoDateTimeSchema: () => isoDateTimeSchema,
1013
1234
  loginMagicLinkConsumeRequestSchema: () => loginMagicLinkConsumeRequestSchema,
1014
1235
  loginMagicLinkRequestSchema: () => loginMagicLinkRequestSchema,
1015
1236
  loginPasswordRequestSchema: () => loginPasswordRequestSchema,
1237
+ mcpCapabilitySchema: () => mcpCapabilitySchema,
1238
+ mcpConsentSchema: () => mcpConsentSchema,
1239
+ mcpGrantSchema: () => mcpGrantSchema,
1240
+ mcpPageSchema: () => mcpPageSchema,
1241
+ mcpSearchSchema: () => mcpSearchSchema,
1242
+ mcpUpdateConnectionSchema: () => mcpUpdateConnectionSchema,
1243
+ moveRoadmapSchema: () => moveRoadmapSchema,
1244
+ onboardingGoalSchema: () => onboardingGoalSchema,
1245
+ onboardingPushChoiceSchema: () => onboardingPushChoiceSchema,
1246
+ onboardingStatusSchema: () => onboardingStatusSchema,
1247
+ onboardingStepSchema: () => onboardingStepSchema,
1016
1248
  passwordSchema: () => passwordSchema,
1017
1249
  platformSchema: () => platformSchema,
1250
+ portalAssetUploadKeySchema: () => portalAssetUploadKeySchema,
1251
+ portalAuthStartSchema: () => portalAuthStartSchema,
1252
+ portalAuthVerifySchema: () => portalAuthVerifySchema,
1253
+ portalEmailSchema: () => portalEmailSchema,
1254
+ portalRequestQuerySchema: () => portalRequestQuerySchema,
1255
+ portalSlugSchema: () => portalSlugSchema,
1256
+ portalSubmissionSchema: () => portalSubmissionSchema,
1257
+ portalVisibilitySchema: () => portalVisibilitySchema,
1258
+ portalVoteSchema: () => portalVoteSchema,
1259
+ reorderContentSchema: () => reorderContentSchema,
1260
+ roadmapQuerySchema: () => roadmapQuerySchema,
1261
+ roadmapStatusSchema: () => roadmapStatusSchema,
1018
1262
  rotateWriteKeySchema: () => rotateWriteKeySchema,
1263
+ saveDocumentSchema: () => saveDocumentSchema,
1264
+ saveRoadmapSchema: () => saveRoadmapSchema,
1019
1265
  signupRequestSchema: () => signupRequestSchema,
1020
1266
  slugSchema: () => slugSchema,
1267
+ subjectRefSchema: () => subjectRefSchema,
1021
1268
  updateAppSchema: () => updateAppSchema,
1269
+ updateCollectionSchema: () => updateCollectionSchema,
1270
+ updateCurrentUserSchema: () => updateCurrentUserSchema,
1271
+ updateOnboardingSchema: () => updateOnboardingSchema,
1272
+ updatePortalAppSchema: () => updatePortalAppSchema,
1273
+ updatePortalSchema: () => updatePortalSchema,
1274
+ updateWorkspaceSchema: () => updateWorkspaceSchema,
1022
1275
  uuidSchema: () => uuidSchema,
1276
+ webAppConfigSchema: () => webAppConfigSchema,
1277
+ webOriginSchema: () => webOriginSchema,
1278
+ webPresentationSchema: () => webPresentationSchema,
1023
1279
  workspaceRoleSchema: () => workspaceRoleSchema,
1280
+ workspaceTimezoneSchema: () => workspaceTimezoneSchema,
1024
1281
  writeKeyEnvironmentSchema: () => writeKeyEnvironmentSchema
1025
1282
  });
1026
1283
  var slugSchema = z.string().min(1).max(64).regex(/^[a-z0-9-]+$/, "Must be lowercase, digits, and dashes only");
@@ -1047,21 +1304,199 @@ var loginMagicLinkRequestSchema = z.object({
1047
1304
  var loginMagicLinkConsumeRequestSchema = z.object({
1048
1305
  token: z.string().min(16).max(512)
1049
1306
  });
1050
- var platformSchema = z.enum(["ios", "android", "react-native", "flutter"]);
1051
- var writeKeyEnvironmentSchema = z.enum(["production", "staging", "development"]);
1052
- var apiTokenScopeSchema = z.enum(["sdk:subjects", "push.transactional"]);
1307
+ var updateCurrentUserSchema = z.object({
1308
+ name: z.string().trim().min(1).max(120).optional()
1309
+ }).strict().refine((value) => Object.keys(value).length > 0, {
1310
+ message: "At least one field is required"
1311
+ });
1312
+ var deliveryPlatformsSchema = z.array(z.enum(["ios", "android", "web"])).min(1).max(3).transform((values) => [...new Set(values)]);
1313
+ var webPresentationSchema = z.object({
1314
+ layout: z.enum(["modal", "card", "panel"]).optional(),
1315
+ size: z.enum(["compact", "standard", "wide"]).optional(),
1316
+ position: z.enum(["left", "right"]).optional(),
1317
+ backdrop: z.boolean().optional()
1318
+ }).strict();
1319
+ var webOriginSchema = z.string().max(2048).refine((value) => {
1320
+ try {
1321
+ const url = new URL(value);
1322
+ return url.origin === value && !url.username && !url.password && (url.protocol === "https:" || url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname));
1323
+ } catch {
1324
+ return false;
1325
+ }
1326
+ }, "Use an exact HTTPS origin, or an HTTP localhost origin for development");
1327
+ var webAppConfigSchema = z.object({
1328
+ allowedOrigins: z.array(webOriginSchema).max(30).transform((values) => [...new Set(values)])
1329
+ }).strict();
1330
+
1331
+ // src/types/portal.ts
1332
+ var PORTAL_RESERVED_SLUGS = [
1333
+ "www",
1334
+ "app",
1335
+ "api",
1336
+ "admin",
1337
+ "auth",
1338
+ "portal",
1339
+ "docs",
1340
+ "status",
1341
+ "mail",
1342
+ "support",
1343
+ "login",
1344
+ "logout",
1345
+ "signup",
1346
+ "billing",
1347
+ "dashboard",
1348
+ "cdn",
1349
+ "assets",
1350
+ "static",
1351
+ "smtp",
1352
+ "ftp",
1353
+ "help",
1354
+ "account",
1355
+ "accounts",
1356
+ "developer"
1357
+ ];
1358
+ var PORTAL_SLUG_PATTERN = /^[a-z0-9](?:[a-z0-9-]{1,46})[a-z0-9]$/;
1359
+ function validPortalSlug(slug) {
1360
+ return PORTAL_SLUG_PATTERN.test(slug) && !PORTAL_RESERVED_SLUGS.includes(slug);
1361
+ }
1362
+ function suggestPortalSlug(name) {
1363
+ const value = name.toLowerCase().normalize("NFKD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 48).replace(/-$/, "");
1364
+ return validPortalSlug(value) ? value : value.length >= 3 ? `${value.slice(0, 40)}-team` : "";
1365
+ }
1366
+ function buildPortalUrl(slug, baseDomain = "usergist.com", appSlug) {
1367
+ if (!validPortalSlug(slug) || !/^[a-z0-9.-]+$/i.test(baseDomain)) throw new Error("Invalid portal address");
1368
+ const base = `https://${slug}.${baseDomain}`;
1369
+ return appSlug ? `${base}/${encodeURIComponent(appSlug)}/requests` : base;
1370
+ }
1371
+
1372
+ // src/schemas/portal.ts
1373
+ var portalSlugSchema = z.string().refine(
1374
+ validPortalSlug,
1375
+ "Use 3\u201348 lowercase letters, numbers, or interior hyphens. This name must not be reserved."
1376
+ );
1377
+ var updatePortalSchema = z.object({
1378
+ displayName: z.string().trim().min(1).max(100).optional(),
1379
+ slug: portalSlugSchema.optional(),
1380
+ setupDismissed: z.boolean().optional()
1381
+ }).strict();
1382
+ var updatePortalAppSchema = z.object({ slug: portalSlugSchema, enabled: z.boolean() }).strict();
1383
+ var portalVisibilitySchema = z.object({ ids: z.array(z.string().uuid()).min(1).max(100), visible: z.boolean() }).strict();
1384
+ var portalEmailSchema = z.string().trim().email().max(254).transform((value) => value.toLowerCase());
1385
+ var portalAuthStartSchema = z.object({ email: portalEmailSchema }).strict();
1386
+ var portalAuthVerifySchema = z.object({ email: portalEmailSchema, code: z.string().regex(/^\d{6}$/) }).strict();
1387
+ var portalSubmissionSchema = z.object({
1388
+ title: z.string().trim().min(1).max(120),
1389
+ description: z.string().trim().min(1).max(1500),
1390
+ idempotencyKey: z.string().uuid(),
1391
+ feedbackConsent: z.literal(true)
1392
+ }).strict();
1393
+ var portalVoteSchema = z.object({ vote: z.boolean(), feedbackConsent: z.literal(true) }).strict();
1394
+ var portalRequestQuerySchema = z.object({
1395
+ q: z.string().trim().max(200).optional(),
1396
+ status: z.enum(["under_review", "planned", "in_progress", "shipped", "declined"]).optional(),
1397
+ sort: z.enum(["top", "newest", "status_changed"]).default("top"),
1398
+ page: z.coerce.number().int().min(1).max(1e5).default(1),
1399
+ limit: z.coerce.number().int().min(1).max(100).default(20)
1400
+ }).strict();
1401
+
1402
+ // src/schemas/apps.ts
1403
+ var workspaceTimezoneSchema = z.string().trim().min(1).max(64).refine(isValidIanaTimeZone, "Enter a valid IANA timezone");
1404
+ var platformSchema = z.enum([
1405
+ "ios",
1406
+ "android",
1407
+ "react-native",
1408
+ "expo",
1409
+ "flutter",
1410
+ "web"
1411
+ ]);
1412
+ var writeKeyEnvironmentSchema = z.enum([
1413
+ "production",
1414
+ "staging",
1415
+ "development"
1416
+ ]);
1417
+ var onboardingGoalSchema = z.enum([
1418
+ "feedback",
1419
+ "survey",
1420
+ "inapp",
1421
+ "push",
1422
+ "requests"
1423
+ ]);
1424
+ var onboardingStatusSchema = z.enum([
1425
+ "in_progress",
1426
+ "deferred",
1427
+ "completed"
1428
+ ]);
1429
+ var onboardingStepSchema = z.enum([
1430
+ "connect",
1431
+ "verify",
1432
+ "experience",
1433
+ "push",
1434
+ "launch"
1435
+ ]);
1436
+ var onboardingPushChoiceSchema = z.enum([
1437
+ "pending",
1438
+ "configured",
1439
+ "skipped"
1440
+ ]);
1441
+ var apiTokenScopeSchema = z.enum([
1442
+ "sdk:subjects",
1443
+ "push.transactional",
1444
+ "users.properties.write"
1445
+ ]);
1053
1446
  var createAppSchema = z.object({
1054
1447
  name: z.string().min(1).max(120),
1055
1448
  slug: slugSchema.optional(),
1056
1449
  platforms: z.array(platformSchema).min(1).max(8),
1057
- environment: writeKeyEnvironmentSchema.default("production")
1450
+ environment: writeKeyEnvironmentSchema.default("production"),
1451
+ onboardingGoal: onboardingGoalSchema.optional(),
1452
+ setupMode: z.enum(["sdk", "portal"]).optional(),
1453
+ portal: z.object({
1454
+ appSlug: portalSlugSchema,
1455
+ company: z.object({
1456
+ displayName: z.string().trim().min(1).max(100),
1457
+ slug: portalSlugSchema
1458
+ }).strict().optional()
1459
+ }).strict().optional(),
1460
+ webConfig: webAppConfigSchema.optional()
1461
+ });
1462
+ var updateOnboardingSchema = z.object({
1463
+ action: z.enum([
1464
+ "resume",
1465
+ "defer",
1466
+ "create_first_inapp",
1467
+ "first_inapp_completed",
1468
+ "create_first_feedback",
1469
+ "first_feedback_completed",
1470
+ "push_configured",
1471
+ "push_skipped",
1472
+ "complete"
1473
+ ]).optional(),
1474
+ step: onboardingStepSchema.optional(),
1475
+ question: z.string().trim().min(1).max(500).optional(),
1476
+ message: z.object({
1477
+ title: z.string().trim().min(1).max(200),
1478
+ body: z.string().trim().min(1).max(500),
1479
+ buttonLabel: z.string().trim().min(1).max(40),
1480
+ format: z.enum(["modal", "slideup"])
1481
+ }).strict().optional()
1482
+ }).refine((value) => Boolean(value.action || value.step), {
1483
+ message: "Provide an onboarding action or step"
1484
+ }).refine(
1485
+ (value) => value.action !== "create_first_feedback" || Boolean(value.question),
1486
+ { message: "Provide a question for the first feedback experience" }
1487
+ );
1488
+ var deferCurrentUserOnboardingSchema = z.object({
1489
+ action: z.literal("defer")
1058
1490
  });
1059
1491
  var updateAppSchema = z.object({
1060
1492
  name: z.string().min(1).max(120).optional(),
1061
1493
  platforms: z.array(platformSchema).min(1).max(8).optional(),
1062
1494
  piiAllowList: z.array(z.string().min(1).max(120)).max(128).optional(),
1063
- lifecycleEventsEnabled: z.boolean().optional()
1064
- }).refine((v) => Object.keys(v).length > 0, { message: "At least one field is required" });
1495
+ lifecycleEventsEnabled: z.boolean().optional(),
1496
+ webConfig: webAppConfigSchema.optional()
1497
+ }).refine((v) => Object.keys(v).length > 0, {
1498
+ message: "At least one field is required"
1499
+ });
1065
1500
  var createWriteKeySchema = z.object({
1066
1501
  label: z.string().min(1).max(120).optional(),
1067
1502
  environment: writeKeyEnvironmentSchema.default("production")
@@ -1076,8 +1511,15 @@ var createApiTokenSchema = z.object({
1076
1511
  expiresInDays: z.number().int().min(1).max(365).default(90)
1077
1512
  });
1078
1513
  var createWorkspaceSchema = z.object({
1079
- name: z.string().min(1).max(120),
1080
- slug: slugSchema.optional()
1514
+ name: z.string().trim().min(1).max(120),
1515
+ slug: slugSchema.optional(),
1516
+ timezone: workspaceTimezoneSchema.default("UTC")
1517
+ });
1518
+ var updateWorkspaceSchema = z.object({
1519
+ name: z.string().trim().min(1).max(120).optional(),
1520
+ timezone: workspaceTimezoneSchema.optional()
1521
+ }).strict().refine((value) => Object.keys(value).length > 0, {
1522
+ message: "At least one field is required"
1081
1523
  });
1082
1524
  var inviteMemberSchema = z.object({
1083
1525
  email: emailSchema,
@@ -1087,6 +1529,714 @@ var acceptWorkspaceInviteSchema = z.object({
1087
1529
  token: z.string().regex(/^[a-f0-9]{64}$/i, "Invalid invitation token")
1088
1530
  });
1089
1531
 
1090
- export { APP_OPEN_EVENT_NAME, APP_VERSION_CHANGED_EVENT_NAME, AUDIENCE_JOIN_EVENT_NAME, AUDIENCE_JOIN_TRIGGER_KIND, BILLING_GRACE_DAYS, COMMERCIAL_BILLING_PLANS, CORE_INTEGRATION_EVENTS, INAPP_AUTO_DISMISSED_EVENT_NAME, INAPP_CTA_CLICKED_EVENT_NAME, INAPP_DISMISSED_EVENT_NAME, INAPP_SHOWN_EVENT_NAME, INTEGRATION_CATEGORIES, INTEGRATION_PROVIDERS, PUSH_EVENTS, RADIUS_PRESETS, RECIPIENTS_LIMIT, REQUEST_COMMENTED_EVENT_NAME, REQUEST_COMMENT_DELETED_EVENT_NAME, REQUEST_COMMENT_EDITED_EVENT_NAME, REQUEST_FOLLOWED_EVENT_NAME, REQUEST_RESPONDED_EVENT_NAME, REQUEST_STATUS_CHANGED_EVENT_NAME, REQUEST_SUBMITTED_EVENT_NAME, REQUEST_UNFOLLOWED_EVENT_NAME, REQUEST_UNUPVOTED_EVENT_NAME, REQUEST_UPVOTED_EVENT_NAME, STARTER_FOUNDING_CUSTOMER_LIMIT, STARTER_FOUNDING_OFFER_CODE, SURVEY_END_SENTINEL, THEME_PRESETS, TRIAL_APP_LIMIT, TRIAL_DAYS, USER_IDENTIFIED_EVENT_NAME, brandTokensFromPreset, defaultEventTrigger, defaultThemePreset, defaultTriggerSpec, emptyAudienceSpec, emptySegmentDsl, endpoints, err, estimateProgress, evaluateBranchCondition, evaluateSegment, evaluateSerializedSegmentRules, findQuestion, findQuestionIndex, getCoreIntegrationEvent, getThemePresetById, inAppColorsFromBrandTokens, isSilentPushPayload, nextPeriodicFire, nextQuestionId, ok, promptThemeFromBrandTokens, reachableQuestions, requestAccentFromBrandTokens, sanitizeCoreIntegrationProperties, schemas_exports as schemas, serializedRulesToDsl, tzOffsetMinutes };
1532
+ // src/types/portal-content.ts
1533
+ function emptyDocumentDraft() {
1534
+ return {
1535
+ title: "",
1536
+ summary: "",
1537
+ body: { type: "doc", content: [{ type: "paragraph" }] },
1538
+ collectionId: null,
1539
+ category: "improved",
1540
+ releaseDate: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
1541
+ version: "",
1542
+ links: []
1543
+ };
1544
+ }
1545
+ function contentText(node2) {
1546
+ return node2.text ?? (node2.content ?? []).map(contentText).join(node2.type === "paragraph" || node2.type === "heading" ? "" : "\n");
1547
+ }
1548
+ function contentAssetIds(node2) {
1549
+ return [
1550
+ .../* @__PURE__ */ new Set([
1551
+ ...node2.type === "image" && node2.attrs?.assetId ? [node2.attrs.assetId] : [],
1552
+ ...(node2.content ?? []).flatMap(contentAssetIds)
1553
+ ])
1554
+ ];
1555
+ }
1556
+ function contentSlug(title) {
1557
+ return title.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 96).replace(/-$/, "") || "article";
1558
+ }
1559
+ function safeContentHref(href) {
1560
+ return /^(https?:\/\/|mailto:|\/[^/]|#[a-zA-Z0-9_-])/.test(href) && !/[\u0000-\u0020\\]/.test(href);
1561
+ }
1562
+
1563
+ // src/schemas/portal-content.ts
1564
+ var uuid = z.string().uuid();
1565
+ var contentKindSchema = z.enum(["article", "changelog"]);
1566
+ var contentStateSchema = z.enum(["draft", "published", "archived"]);
1567
+ var roadmapStatusSchema = z.enum(["planned", "in_progress", "shipped"]);
1568
+ var contentLinkSchema = z.object({ kind: z.enum(["request", "roadmap"]), id: uuid }).strict();
1569
+ var mark = z.object({
1570
+ type: z.enum(["bold", "italic", "code", "link"]),
1571
+ attrs: z.object({ href: z.string().max(2048).refine(safeContentHref, "Use a safe link URL") }).strict().optional()
1572
+ }).strict().refine((m) => m.type === "link" ? Boolean(m.attrs) : !m.attrs);
1573
+ var node = z.lazy(
1574
+ () => z.object({
1575
+ type: z.enum([
1576
+ "doc",
1577
+ "paragraph",
1578
+ "heading",
1579
+ "text",
1580
+ "bulletList",
1581
+ "orderedList",
1582
+ "listItem",
1583
+ "blockquote",
1584
+ "codeBlock",
1585
+ "hardBreak",
1586
+ "image"
1587
+ ]),
1588
+ text: z.string().max(1e5).optional(),
1589
+ attrs: z.object({
1590
+ level: z.number().int().min(2).max(3).optional(),
1591
+ start: z.number().int().min(1).max(1e4).optional(),
1592
+ language: z.string().max(40).nullable().optional(),
1593
+ assetId: uuid.optional(),
1594
+ alt: z.string().max(500).optional()
1595
+ }).strict().optional(),
1596
+ marks: z.array(mark).max(4).optional(),
1597
+ content: z.array(node).max(5e3).optional()
1598
+ }).strict()
1599
+ );
1600
+ var contentBodySchema = z.unknown().superRefine((value, ctx) => {
1601
+ let count = 0, invalid = false;
1602
+ const walk = (v, depth) => {
1603
+ if (depth > 20 || ++count > 5e3) {
1604
+ invalid = true;
1605
+ return;
1606
+ }
1607
+ if (v && typeof v === "object" && "content" in v && Array.isArray(v.content))
1608
+ for (const child of v.content) {
1609
+ if (invalid) break;
1610
+ walk(child, depth + 1);
1611
+ }
1612
+ };
1613
+ walk(value, 0);
1614
+ if (invalid)
1615
+ ctx.addIssue({
1616
+ code: z.ZodIssueCode.custom,
1617
+ message: "Document is too deeply nested or contains too many blocks"
1618
+ });
1619
+ }).pipe(node).superRefine((value, ctx) => {
1620
+ if (value.type !== "doc" || contentText(value).length > 1e5)
1621
+ ctx.addIssue({
1622
+ code: z.ZodIssueCode.custom,
1623
+ message: "Invalid document or body exceeds 100,000 characters"
1624
+ });
1625
+ const walk = (v, root = false) => {
1626
+ const blocks = ["paragraph", "heading", "bulletList", "orderedList", "blockquote", "codeBlock", "image"];
1627
+ const children = v.content ?? [];
1628
+ const allowed = v.type === "doc" || v.type === "blockquote" ? blocks : v.type === "listItem" ? blocks.filter((t) => t !== "heading") : v.type === "bulletList" || v.type === "orderedList" ? ["listItem"] : v.type === "paragraph" || v.type === "heading" ? ["text", "hardBreak"] : v.type === "codeBlock" ? ["text"] : [];
1629
+ const attrs = Object.keys(v.attrs ?? {});
1630
+ const allowedAttrs = v.type === "heading" ? ["level"] : v.type === "orderedList" ? ["start"] : v.type === "codeBlock" ? ["language"] : v.type === "image" ? ["assetId", "alt"] : [];
1631
+ if (!root && v.type === "doc" || v.type === "text" && (!v.text || v.content) || v.type !== "text" && (v.text !== void 0 || Boolean(v.marks?.length)) || v.type === "image" && (!v.attrs?.assetId || v.content) || v.type === "heading" && !v.attrs?.level || attrs.some((a) => !allowedAttrs.includes(a)) || children.some((c) => !allowed.includes(c.type)) || v.type === "listItem" && children[0]?.type !== "paragraph" || ["bulletList", "orderedList", "blockquote", "doc"].includes(v.type) && !children.length || v.type === "codeBlock" && children.some((c) => c.marks?.length))
1632
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Invalid content block" });
1633
+ v.content?.forEach((c) => walk(c));
1634
+ };
1635
+ walk(value, true);
1636
+ });
1637
+ var documentDraftSchema = z.object({
1638
+ title: z.string().trim().max(160),
1639
+ summary: z.string().max(280),
1640
+ body: contentBodySchema,
1641
+ collectionId: uuid.nullable(),
1642
+ category: z.enum(["new", "improved", "fixed"]),
1643
+ releaseDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(
1644
+ (v) => !Number.isNaN(Date.parse(v)) && new Date(v).toISOString().slice(0, 10) === v,
1645
+ "Choose a valid date"
1646
+ ),
1647
+ version: z.string().max(40),
1648
+ links: z.array(contentLinkSchema).max(100)
1649
+ }).strict();
1650
+ var createDocumentSchema = z.object({
1651
+ idempotencyKey: uuid,
1652
+ title: z.string().trim().max(160).optional(),
1653
+ collectionId: uuid.nullable().optional(),
1654
+ links: z.array(contentLinkSchema).max(100).optional()
1655
+ }).strict();
1656
+ var saveDocumentSchema = z.object({ revision: z.number().int().positive(), draft: documentDraftSchema }).strict();
1657
+ var contentActionSchema = z.object({
1658
+ revision: z.number().int().positive(),
1659
+ action: z.enum(["publish", "unpublish", "archive", "restore"])
1660
+ }).strict();
1661
+ var contentQuerySchema = z.object({
1662
+ q: z.string().trim().max(200).optional(),
1663
+ state: contentStateSchema.optional(),
1664
+ collectionId: uuid.optional(),
1665
+ category: z.enum(["new", "improved", "fixed"]).optional(),
1666
+ cursor: z.string().max(2e3).optional(),
1667
+ limit: z.coerce.number().int().min(1).max(50).default(20)
1668
+ }).strict();
1669
+ var createCollectionSchema = z.object({
1670
+ title: z.string().trim().min(1).max(160),
1671
+ description: z.string().max(280),
1672
+ idempotencyKey: uuid
1673
+ }).strict();
1674
+ var contentPageQuerySchema = contentQuerySchema.pick({ cursor: true, limit: true });
1675
+ var portalAssetUploadKeySchema = uuid;
1676
+ var updateCollectionSchema = z.object({
1677
+ revision: z.number().int().positive(),
1678
+ title: z.string().trim().min(1).max(160).optional(),
1679
+ description: z.string().max(280).optional(),
1680
+ archived: z.boolean().optional()
1681
+ }).strict();
1682
+ var reorderContentSchema = z.object({ revision: z.number().int().positive(), direction: z.enum(["up", "down"]) }).strict();
1683
+ var roadmapQuerySchema = z.object({
1684
+ status: roadmapStatusSchema,
1685
+ cursor: z.string().max(2e3).optional(),
1686
+ limit: z.coerce.number().int().min(1).max(50).default(20),
1687
+ archived: z.enum(["true", "false"]).transform((v) => v === "true").optional()
1688
+ }).strict();
1689
+ var roadmapFields = {
1690
+ title: z.string().trim().min(1).max(120),
1691
+ description: z.string().max(1500),
1692
+ requestIds: z.array(uuid).max(100).refine((v) => new Set(v).size === v.length)
1693
+ };
1694
+ var createRoadmapSchema = z.object({ ...roadmapFields, idempotencyKey: uuid, status: roadmapStatusSchema }).strict();
1695
+ var saveRoadmapSchema = z.object({ ...roadmapFields, revision: z.number().int().positive() }).strict();
1696
+ var moveRoadmapSchema = z.object({
1697
+ revision: z.number().int().positive(),
1698
+ status: roadmapStatusSchema,
1699
+ requests: z.array(z.object({ id: uuid, updatedAt: z.string().datetime() }).strict()).max(100).refine((v) => new Set(v.map((r) => r.id)).size === v.length)
1700
+ }).strict();
1701
+ var contentLinkQuerySchema = z.object({
1702
+ kind: z.enum(["request", "roadmap"]),
1703
+ q: z.string().trim().max(200).optional(),
1704
+ cursor: z.string().max(2e3).optional(),
1705
+ limit: z.coerce.number().int().min(1).max(100).default(20),
1706
+ ids: z.string().max(4e3).optional().refine((v) => !v || v.split(",").every((id2) => uuid.safeParse(id2).success), "Invalid linked IDs")
1707
+ }).strict();
1708
+
1709
+ // src/types/mcp.ts
1710
+ var MCP_DOMAINS = ["context", "users", "analytics", "requests", "roadmap", "content", "experiences", "segments", "brand", "portal", "push", "integrations", "sdk", "apps"];
1711
+ var MCP_ACCESS_MODES = ["read_only", "approve_changes", "automatic"];
1712
+ var MCP_CAPABILITIES = [
1713
+ "context:read",
1714
+ "users:read",
1715
+ "analytics:read",
1716
+ "requests:read",
1717
+ "requests:manage",
1718
+ "requests:publish",
1719
+ "roadmap:read",
1720
+ "roadmap:manage",
1721
+ "roadmap:publish",
1722
+ "content:read",
1723
+ "content:manage",
1724
+ "content:publish",
1725
+ "experiences:read",
1726
+ "experiences:manage",
1727
+ "experiences:publish",
1728
+ "segments:read",
1729
+ "segments:manage",
1730
+ "brand:read",
1731
+ "brand:manage",
1732
+ "portal:read",
1733
+ "portal:manage",
1734
+ "portal:publish",
1735
+ "push:read",
1736
+ "push:manage",
1737
+ "push:send",
1738
+ "integrations:read",
1739
+ "integrations:manage",
1740
+ "integrations:send",
1741
+ "sdk:read",
1742
+ "sdk:manage",
1743
+ "apps:read",
1744
+ "apps:manage"
1745
+ ];
1746
+ var MCP_DEFAULT_CAPABILITIES = [
1747
+ "context:read",
1748
+ "users:read",
1749
+ "analytics:read",
1750
+ "requests:read",
1751
+ "roadmap:read",
1752
+ "content:read",
1753
+ "experiences:read",
1754
+ "segments:read",
1755
+ "brand:read",
1756
+ "portal:read",
1757
+ "push:read",
1758
+ "sdk:read",
1759
+ "apps:read",
1760
+ "requests:manage",
1761
+ "roadmap:manage",
1762
+ "content:manage",
1763
+ "experiences:manage",
1764
+ "segments:manage"
1765
+ ];
1766
+
1767
+ // src/schemas/mcp.ts
1768
+ var mcpCapabilitySchema = z.string().refine((value) => MCP_CAPABILITIES.includes(value), "Unknown MCP capability");
1769
+ var mcpGrantSchema = z.object({
1770
+ name: z.string().trim().min(1).max(100).default("AI connection"),
1771
+ appIds: z.array(z.string().uuid()).min(1).max(100).refine((v) => new Set(v).size === v.length, "Duplicate app IDs"),
1772
+ capabilities: z.array(mcpCapabilitySchema).max(56).default([...MCP_DEFAULT_CAPABILITIES]),
1773
+ mode: z.enum(MCP_ACCESS_MODES).default("approve_changes")
1774
+ }).strict();
1775
+ var mcpConsentSchema = mcpGrantSchema.extend({
1776
+ workspaceId: z.string().uuid(),
1777
+ externalAuthId: z.string().min(10).max(256).regex(/^[a-zA-Z0-9_-]+$/)
1778
+ });
1779
+ var mcpUpdateConnectionSchema = mcpGrantSchema.extend({ policyVersion: z.number().int().positive() });
1780
+ var subjectRefSchema = z.union([
1781
+ z.object({ subjectId: z.string().uuid() }).strict(),
1782
+ z.object({ externalId: z.string().min(1).max(256) }).strict(),
1783
+ z.object({ anonymousId: z.string().min(1).max(256) }).strict()
1784
+ ]);
1785
+ var mcpPageSchema = z.object({ cursor: z.string().max(4096).optional(), limit: z.number().int().min(1).max(100).default(25) });
1786
+ var mcpSearchSchema = mcpPageSchema.extend({
1787
+ query: z.string().trim().min(1).max(500),
1788
+ types: z.array(z.enum(["request", "feedback_answer", "survey_answer", "roadmap", "article", "changelog"])).max(6).optional(),
1789
+ variant: z.enum(["draft", "published", "record"]).optional()
1790
+ });
1791
+
1792
+ // src/types/web.ts
1793
+ var DELIVERY_PROTOCOL_VERSION = 2;
1794
+ function deliveryPlatformsForApp(platforms) {
1795
+ const values = /* @__PURE__ */ new Set();
1796
+ for (const platform of platforms) {
1797
+ if (platform === "web" || platform === "ios" || platform === "android") values.add(platform);
1798
+ if (platform === "expo" || platform === "react-native" || platform === "flutter") {
1799
+ values.add("ios");
1800
+ values.add("android");
1801
+ }
1802
+ }
1803
+ return [...values];
1804
+ }
1805
+ function resolveWebPresentation(pillar, override) {
1806
+ return {
1807
+ layout: override?.layout ?? "modal",
1808
+ size: override?.size ?? (pillar === "requests" ? "wide" : "standard"),
1809
+ position: override?.position ?? "right",
1810
+ backdrop: override?.backdrop ?? override?.layout !== "card"
1811
+ };
1812
+ }
1813
+ var id = z.string().regex(/^[A-Za-z][A-Za-z0-9_]{0,63}$/);
1814
+ var key = z.string().min(1).max(120).refine(
1815
+ (v) => !["__proto__", "prototype", "constructor"].includes(v),
1816
+ "Reserved property key"
1817
+ );
1818
+ var scalar = z.union([
1819
+ z.string().max(8192),
1820
+ z.number().finite(),
1821
+ z.boolean(),
1822
+ z.null()
1823
+ ]);
1824
+ var baseSource = { id, label: z.string().min(1).max(120) };
1825
+ var filterSchema = z.object({
1826
+ key,
1827
+ op: z.enum([
1828
+ "eq",
1829
+ "neq",
1830
+ "gt",
1831
+ "gte",
1832
+ "lt",
1833
+ "lte",
1834
+ "in",
1835
+ "nin",
1836
+ "contains",
1837
+ "starts_with",
1838
+ "exists",
1839
+ "not_exists"
1840
+ ]),
1841
+ value: z.union([
1842
+ z.string(),
1843
+ z.number().finite(),
1844
+ z.boolean(),
1845
+ z.array(z.union([z.string(), z.number().finite()])).max(100)
1846
+ ]).optional()
1847
+ });
1848
+ var personalizationSpecSchema = z.object({
1849
+ version: z.literal(1),
1850
+ sources: z.array(
1851
+ z.discriminatedUnion("kind", [
1852
+ z.object({ ...baseSource, kind: z.literal("user_property") }),
1853
+ z.object({ ...baseSource, kind: z.literal("trigger_event") }),
1854
+ z.object({ ...baseSource, kind: z.literal("send_data") }),
1855
+ z.object({ ...baseSource, kind: z.literal("app") }),
1856
+ z.object({ ...baseSource, kind: z.literal("now") }),
1857
+ z.object({
1858
+ ...baseSource,
1859
+ kind: z.literal("latest_event"),
1860
+ eventName: z.string().min(1).max(120),
1861
+ lookbackDays: z.number().int().min(1).max(90),
1862
+ filters: z.array(filterSchema).max(8).optional()
1863
+ })
1864
+ ])
1865
+ ).max(16),
1866
+ bindings: z.array(
1867
+ z.object({
1868
+ id,
1869
+ label: z.string().min(1).max(120),
1870
+ sourceId: id,
1871
+ key,
1872
+ type: z.enum(["string", "number", "boolean", "date"]),
1873
+ fallback: scalar.optional()
1874
+ })
1875
+ ).max(64),
1876
+ missingData: z.literal("skip")
1877
+ }).superRefine((spec, ctx) => {
1878
+ const sources = new Set(spec.sources.map((source) => source.id));
1879
+ if (sources.size !== spec.sources.length)
1880
+ ctx.addIssue({
1881
+ code: "custom",
1882
+ path: ["sources"],
1883
+ message: "Source IDs must be unique"
1884
+ });
1885
+ if (spec.sources.filter((source) => source.kind === "latest_event").length > 4)
1886
+ ctx.addIssue({
1887
+ code: "custom",
1888
+ path: ["sources"],
1889
+ message: "Use at most four activity sources"
1890
+ });
1891
+ const bindings = /* @__PURE__ */ new Set();
1892
+ spec.bindings.forEach((binding, index) => {
1893
+ if (bindings.has(binding.id))
1894
+ ctx.addIssue({
1895
+ code: "custom",
1896
+ path: ["bindings", index, "id"],
1897
+ message: "Field IDs must be unique"
1898
+ });
1899
+ bindings.add(binding.id);
1900
+ if (!sources.has(binding.sourceId))
1901
+ ctx.addIssue({
1902
+ code: "custom",
1903
+ path: ["bindings", index, "sourceId"],
1904
+ message: "Choose an existing source"
1905
+ });
1906
+ if (binding.fallback !== void 0 && (isMissing(binding.fallback) || !matchesType(binding.fallback, binding.type)))
1907
+ ctx.addIssue({
1908
+ code: "custom",
1909
+ path: ["bindings", index, "fallback"],
1910
+ message: "Fallback must be a non-empty value of the selected type"
1911
+ });
1912
+ });
1913
+ });
1914
+ var userPropertiesUpdateSchema = z.object({
1915
+ mutationId: z.string().uuid(),
1916
+ set: z.record(key, scalar).refine(
1917
+ (v) => Object.keys(v).length <= 64,
1918
+ "Update at most 64 properties"
1919
+ ).optional(),
1920
+ unset: z.array(key).max(64).optional()
1921
+ }).superRefine((update, ctx) => {
1922
+ if (!Object.keys(update.set ?? {}).length && !update.unset?.length)
1923
+ ctx.addIssue({
1924
+ code: "custom",
1925
+ message: "Supply properties to set or remove"
1926
+ });
1927
+ if (update.unset?.some((name) => Object.hasOwn(update.set ?? {}, name)))
1928
+ ctx.addIssue({
1929
+ code: "custom",
1930
+ message: "A property cannot be set and removed in the same update"
1931
+ });
1932
+ });
1933
+ function isMissing(value) {
1934
+ return value == null || typeof value === "string" && !value.trim();
1935
+ }
1936
+ function matchesType(value, type) {
1937
+ if (type === "date")
1938
+ return typeof value === "string" && !Number.isNaN(Date.parse(value));
1939
+ return typeof value === type && (typeof value !== "number" || Number.isFinite(value));
1940
+ }
1941
+ function resolvePersonalizationBindings(spec, sources) {
1942
+ const values = /* @__PURE__ */ Object.create(null);
1943
+ const issues = [];
1944
+ const fallbackBindingIds = [];
1945
+ for (const binding of spec.bindings) {
1946
+ const source = sources[binding.sourceId]?.values;
1947
+ const value = source && Object.hasOwn(source, binding.key) ? source[binding.key] : void 0;
1948
+ const missing = isMissing(value);
1949
+ if (!missing && matchesType(value, binding.type))
1950
+ values[binding.id] = value;
1951
+ else if (missing && binding.fallback !== void 0) {
1952
+ values[binding.id] = binding.fallback;
1953
+ fallbackBindingIds.push(binding.id);
1954
+ } else
1955
+ issues.push({
1956
+ code: missing ? "missing" : "type_mismatch",
1957
+ bindingId: binding.id,
1958
+ message: missing ? `${binding.label} is missing` : `${binding.label} must be ${binding.type}`
1959
+ });
1960
+ }
1961
+ return {
1962
+ status: issues.length ? "skipped" : fallbackBindingIds.length ? "using_fallback" : "ready",
1963
+ values,
1964
+ fallbackBindingIds,
1965
+ issues,
1966
+ sources
1967
+ };
1968
+ }
1969
+ var TOKEN = /\{\{\s*p\.([A-Za-z][A-Za-z0-9_]*)\s*\}\}/g;
1970
+ var WHOLE_TOKEN = /^\{\{\s*p\.([A-Za-z][A-Za-z0-9_]*)\s*\}\}$/;
1971
+ function personalizationToken(bindingId) {
1972
+ return `{{p.${bindingId}}}`;
1973
+ }
1974
+ function renderPersonalizedValue(input, values, issues, path = "", mode = "text") {
1975
+ if (typeof input === "string") {
1976
+ const whole = WHOLE_TOKEN.exec(input);
1977
+ const lookup = (bindingId) => {
1978
+ if (Object.hasOwn(values, bindingId)) return values[bindingId];
1979
+ issues.push({
1980
+ code: "unknown_binding",
1981
+ bindingId,
1982
+ path,
1983
+ message: `No value is available for ${bindingId}`
1984
+ });
1985
+ return null;
1986
+ };
1987
+ if (mode === "json" && whole) return lookup(whole[1]);
1988
+ if (/\{\{|\}\}/.test(input.replace(TOKEN, "")))
1989
+ issues.push({
1990
+ code: "invalid_template",
1991
+ path,
1992
+ message: "Insert a valid dynamic field"
1993
+ });
1994
+ const result = input.replace(TOKEN, (_, bindingId) => {
1995
+ const value = lookup(bindingId);
1996
+ return mode === "url" && !whole ? encodeURIComponent(String(value ?? "")) : String(value ?? "");
1997
+ });
1998
+ if (mode === "url" && result) {
1999
+ try {
2000
+ const url = new URL(result);
2001
+ if (["javascript:", "data:", "file:", "vbscript:"].includes(url.protocol))
2002
+ throw new Error("unsafe");
2003
+ if (!whole && /\{\{/.test(input.split(/:\/\//)[0] ?? ""))
2004
+ throw new Error("dynamic scheme");
2005
+ if (!whole && /\{\{/.test(
2006
+ input.match(/^[a-z][a-z0-9+.-]*:\/\/([^/?#]*)/i)?.[1] ?? ""
2007
+ ))
2008
+ throw new Error("dynamic authority");
2009
+ } catch {
2010
+ issues.push({
2011
+ code: "invalid_destination",
2012
+ path,
2013
+ message: "The resolved destination must be a valid app link or web URL"
2014
+ });
2015
+ }
2016
+ }
2017
+ return result;
2018
+ }
2019
+ if (Array.isArray(input))
2020
+ return input.map(
2021
+ (item, index) => renderPersonalizedValue(item, values, issues, `${path}/${index}`, mode)
2022
+ );
2023
+ if (input && typeof input === "object") {
2024
+ const result = /* @__PURE__ */ Object.create(null);
2025
+ for (const [name, value] of Object.entries(input)) {
2026
+ if (["__proto__", "constructor", "prototype"].includes(name)) {
2027
+ issues.push({
2028
+ code: "invalid_template",
2029
+ path,
2030
+ message: "Reserved object key"
2031
+ });
2032
+ continue;
2033
+ }
2034
+ result[name] = renderPersonalizedValue(
2035
+ value,
2036
+ values,
2037
+ issues,
2038
+ `${path}/${name}`,
2039
+ mode
2040
+ );
2041
+ }
2042
+ return result;
2043
+ }
2044
+ return input;
2045
+ }
2046
+ var TEXT_KEYS = /* @__PURE__ */ new Set([
2047
+ "title",
2048
+ "body",
2049
+ "subtitle",
2050
+ "headline",
2051
+ "label",
2052
+ "placeholder",
2053
+ "followUp",
2054
+ "lowLabel",
2055
+ "highLabel",
2056
+ "description",
2057
+ "buttonText",
2058
+ "submitLabel",
2059
+ "nextLabel",
2060
+ "backLabel",
2061
+ "text"
2062
+ ]);
2063
+ var URL_KEYS = /* @__PURE__ */ new Set(["imageUrl", "deepLink", "target"]);
2064
+ var CONTENT_KEYS = /* @__PURE__ */ new Set([
2065
+ "questions",
2066
+ "options",
2067
+ "ctas",
2068
+ "cta",
2069
+ "actionButtons",
2070
+ "flow",
2071
+ "welcome",
2072
+ "thankYou",
2073
+ "completion",
2074
+ "endScreen",
2075
+ "openAction"
2076
+ ]);
2077
+ function personalizationUsage(content) {
2078
+ const usage = /* @__PURE__ */ new Map();
2079
+ const scan = (value, field) => {
2080
+ if (typeof value === "string") {
2081
+ for (const match of value.matchAll(TOKEN)) {
2082
+ const fields = usage.get(match[1]) ?? /* @__PURE__ */ new Set();
2083
+ fields.add(field);
2084
+ usage.set(match[1], fields);
2085
+ }
2086
+ } else if (Array.isArray(value)) value.forEach((item) => scan(item, field));
2087
+ else if (value && typeof value === "object")
2088
+ Object.values(value).forEach((item) => scan(item, field));
2089
+ };
2090
+ const walk = (value) => {
2091
+ if (Array.isArray(value)) {
2092
+ value.forEach(walk);
2093
+ return;
2094
+ }
2095
+ if (!value || typeof value !== "object") return;
2096
+ for (const [key2, item] of Object.entries(value)) {
2097
+ if (TEXT_KEYS.has(key2) || URL_KEYS.has(key2) || key2 === "actionJson" || key2 === "payloadExtras")
2098
+ scan(item, key2);
2099
+ else if (CONTENT_KEYS.has(key2)) walk(item);
2100
+ }
2101
+ };
2102
+ walk(content);
2103
+ return usage;
2104
+ }
2105
+ function renderPersonalizedContent(content, resolution) {
2106
+ const usage = personalizationUsage(content);
2107
+ const onlyOptionalImage = (id2) => usage.get(id2)?.size === 1 && usage.get(id2)?.has("imageUrl");
2108
+ const issues = resolution.issues.filter(
2109
+ (issue) => !issue.bindingId || usage.has(issue.bindingId) && !(issue.code === "missing" && onlyOptionalImage(issue.bindingId))
2110
+ );
2111
+ const fallbacks = resolution.fallbackBindingIds.filter((id2) => usage.has(id2));
2112
+ const walk = (value, path = "") => {
2113
+ if (Array.isArray(value))
2114
+ return value.map((item, index) => walk(item, `${path}/${index}`));
2115
+ if (!value || typeof value !== "object") return value;
2116
+ return Object.fromEntries(
2117
+ Object.entries(value).map(([name, item]) => {
2118
+ const childPath = `${path}/${name}`;
2119
+ if (TEXT_KEYS.has(name) && typeof item === "string")
2120
+ return [
2121
+ name,
2122
+ renderPersonalizedValue(item, resolution.values, issues, childPath)
2123
+ ];
2124
+ if (URL_KEYS.has(name) && typeof item === "string") {
2125
+ if (name === "imageUrl" && [...item.matchAll(TOKEN)].some(
2126
+ (match) => resolution.issues.some(
2127
+ (issue) => issue.bindingId === match[1] && issue.code === "missing"
2128
+ )
2129
+ ))
2130
+ return [name, null];
2131
+ const isEvent = name === "target" && value.action === "custom_event";
2132
+ const rendered2 = renderPersonalizedValue(
2133
+ item,
2134
+ resolution.values,
2135
+ issues,
2136
+ childPath,
2137
+ isEvent ? "text" : "url"
2138
+ );
2139
+ if (name === "imageUrl" && rendered2 && !String(rendered2).startsWith("https://"))
2140
+ issues.push({
2141
+ code: "invalid_destination",
2142
+ path: childPath,
2143
+ message: "Image URLs must use HTTPS"
2144
+ });
2145
+ return [name, rendered2];
2146
+ }
2147
+ if (name === "actionJson" || name === "payloadExtras")
2148
+ return [
2149
+ name,
2150
+ renderPersonalizedValue(
2151
+ item,
2152
+ resolution.values,
2153
+ issues,
2154
+ childPath,
2155
+ "json"
2156
+ )
2157
+ ];
2158
+ if (CONTENT_KEYS.has(name)) return [name, walk(item, childPath)];
2159
+ return [name, item];
2160
+ })
2161
+ );
2162
+ };
2163
+ const rendered = walk(content);
2164
+ return {
2165
+ content: rendered,
2166
+ resolution: {
2167
+ ...resolution,
2168
+ fallbackBindingIds: fallbacks,
2169
+ status: issues.length ? "skipped" : fallbacks.length ? "using_fallback" : "ready",
2170
+ issues
2171
+ }
2172
+ };
2173
+ }
2174
+
2175
+ // src/presentation.ts
2176
+ var PresentationGate = class {
2177
+ paused;
2178
+ identity = 0;
2179
+ revisions = { feedback: 0, survey: 0 };
2180
+ listeners = /* @__PURE__ */ new Set();
2181
+ constructor(paused = false) {
2182
+ this.paused = paused;
2183
+ }
2184
+ get isPaused() {
2185
+ return this.paused;
2186
+ }
2187
+ setPaused(paused) {
2188
+ this.paused = paused;
2189
+ this.notify();
2190
+ }
2191
+ invalidate(purpose) {
2192
+ if (purpose) this.revisions[purpose]++;
2193
+ else this.identity++;
2194
+ this.notify();
2195
+ }
2196
+ validator(purpose) {
2197
+ const identity = this.identity;
2198
+ const revision = this.revisions[purpose];
2199
+ return () => identity === this.identity && revision === this.revisions[purpose];
2200
+ }
2201
+ subscribe(listener) {
2202
+ this.listeners.add(listener);
2203
+ return () => {
2204
+ this.listeners.delete(listener);
2205
+ };
2206
+ }
2207
+ runWhenReady(run, valid, cancel = () => {
2208
+ }) {
2209
+ if (!valid()) {
2210
+ cancel();
2211
+ return;
2212
+ }
2213
+ if (!this.paused) {
2214
+ run();
2215
+ return;
2216
+ }
2217
+ const stop = this.subscribe(() => {
2218
+ if (valid() && this.paused) return;
2219
+ stop();
2220
+ if (valid()) run();
2221
+ else cancel();
2222
+ });
2223
+ }
2224
+ waitUntilReady(valid) {
2225
+ if (!valid()) return Promise.resolve(false);
2226
+ if (!this.paused) return Promise.resolve(true);
2227
+ return new Promise((resolve) => {
2228
+ const stop = this.subscribe(() => {
2229
+ if (valid() && this.paused) return;
2230
+ stop();
2231
+ resolve(valid());
2232
+ });
2233
+ });
2234
+ }
2235
+ notify() {
2236
+ for (const listener of [...this.listeners]) listener();
2237
+ }
2238
+ };
2239
+
2240
+ export { APP_OPEN_EVENT_NAME, APP_VERSION_CHANGED_EVENT_NAME, AUDIENCE_JOIN_EVENT_NAME, AUDIENCE_JOIN_TRIGGER_KIND, BILLING_GRACE_DAYS, COMMERCIAL_BILLING_PLANS, CORE_INTEGRATION_EVENTS, DELIVERY_PROTOCOL_VERSION, INAPP_AUTO_DISMISSED_EVENT_NAME, INAPP_CTA_CLICKED_EVENT_NAME, INAPP_DISMISSED_EVENT_NAME, INAPP_SHOWN_EVENT_NAME, INTEGRATION_CATEGORIES, INTEGRATION_PROVIDERS, MCP_ACCESS_MODES, MCP_CAPABILITIES, MCP_DEFAULT_CAPABILITIES, MCP_DOMAINS, PORTAL_RESERVED_SLUGS, PORTAL_SLUG_PATTERN, PUSH_EVENTS, PresentationGate, RADIUS_PRESETS, RECIPIENTS_LIMIT, REQUEST_COMMENTED_EVENT_NAME, REQUEST_COMMENT_DELETED_EVENT_NAME, REQUEST_COMMENT_EDITED_EVENT_NAME, REQUEST_FOLLOWED_EVENT_NAME, REQUEST_RESPONDED_EVENT_NAME, REQUEST_STATUS_CHANGED_EVENT_NAME, REQUEST_SUBMITTED_EVENT_NAME, REQUEST_UNFOLLOWED_EVENT_NAME, REQUEST_UNUPVOTED_EVENT_NAME, REQUEST_UPVOTED_EVENT_NAME, STARTER_FOUNDING_CUSTOMER_LIMIT, STARTER_FOUNDING_OFFER_CODE, SURVEY_END_SENTINEL, THEME_PRESETS, TRIAL_APP_LIMIT, TRIAL_DAYS, USER_IDENTIFIED_EVENT_NAME, brandTokensFromPreset, buildPortalUrl, contentAssetIds, contentSlug, contentText, defaultEventTrigger, defaultOnboardingMessage, defaultThemePreset, defaultTriggerSpec, deliveryPlatformsForApp, emptyAudienceSpec, emptyDocumentDraft, emptySegmentDsl, endpoints, err, estimateProgress, evaluateBranchCondition, evaluateSegment, evaluateSerializedSegmentRules, findQuestion, findQuestionIndex, getCoreIntegrationEvent, getThemePresetById, inAppColorsFromBrandTokens, isSilentPushPayload, isValidIanaTimeZone, nextPeriodicFire, nextQuestionId, ok, personalizationSpecSchema, personalizationToken, personalizationUsage, promptThemeFromBrandTokens, reachableQuestions, renderPersonalizedContent, renderPersonalizedValue, requestAccentFromBrandTokens, resolvePersonalizationBindings, resolveWebPresentation, safeContentHref, sanitizeCoreIntegrationProperties, schemas_exports as schemas, serializedRulesToDsl, suggestPortalSlug, tzOffsetMinutes, userPropertiesUpdateSchema, validPortalSlug, zonedDateEndToUtc, zonedDateTimeParts, zonedDateTimeToUtc };
1091
2241
  //# sourceMappingURL=index.js.map
1092
2242
  //# sourceMappingURL=index.js.map