@usergist/feedback-react-native 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +231 -0
  4. package/UserGistFeedback.podspec +31 -0
  5. package/UserGistFeedbackExtension.podspec +23 -0
  6. package/android/build.gradle +92 -0
  7. package/android/consumer-rules.pro +5 -0
  8. package/android/src/main/AndroidManifest.xml +31 -0
  9. package/android/src/main/java/studio/usergist/feedback/UserGistFirebaseMessagingService.kt +153 -0
  10. package/android/src/main/java/studio/usergist/feedback/UserGistPushModule.kt +344 -0
  11. package/android/src/main/java/studio/usergist/feedback/UserGistPushPackage.kt +18 -0
  12. package/dist/NativeUserGistPush.d.ts +35 -0
  13. package/dist/NativeUserGistPush.d.ts.map +1 -0
  14. package/dist/NativeUserGistPush.js +13 -0
  15. package/dist/NativeUserGistPush.js.map +1 -0
  16. package/dist/Provider.d.ts +7 -0
  17. package/dist/Provider.d.ts.map +1 -0
  18. package/dist/Provider.js +300 -0
  19. package/dist/Provider.js.map +1 -0
  20. package/dist/Push.d.ts +103 -0
  21. package/dist/Push.d.ts.map +1 -0
  22. package/dist/Push.js +225 -0
  23. package/dist/Push.js.map +1 -0
  24. package/dist/UserGist.d.ts +210 -0
  25. package/dist/UserGist.d.ts.map +1 -0
  26. package/dist/UserGist.js +1246 -0
  27. package/dist/UserGist.js.map +1 -0
  28. package/dist/index.d.ts +11 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +4 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/internal/consent.d.ts +17 -0
  33. package/dist/internal/consent.d.ts.map +1 -0
  34. package/dist/internal/consent.js +98 -0
  35. package/dist/internal/consent.js.map +1 -0
  36. package/dist/internal/context.d.ts +12 -0
  37. package/dist/internal/context.d.ts.map +1 -0
  38. package/dist/internal/context.js +70 -0
  39. package/dist/internal/context.js.map +1 -0
  40. package/dist/internal/debug.d.ts +14 -0
  41. package/dist/internal/debug.d.ts.map +1 -0
  42. package/dist/internal/debug.js +73 -0
  43. package/dist/internal/debug.js.map +1 -0
  44. package/dist/internal/engine.d.ts +93 -0
  45. package/dist/internal/engine.d.ts.map +1 -0
  46. package/dist/internal/engine.js +904 -0
  47. package/dist/internal/engine.js.map +1 -0
  48. package/dist/internal/events.d.ts +49 -0
  49. package/dist/internal/events.d.ts.map +1 -0
  50. package/dist/internal/events.js +71 -0
  51. package/dist/internal/events.js.map +1 -0
  52. package/dist/internal/frequency-cap.d.ts +15 -0
  53. package/dist/internal/frequency-cap.d.ts.map +1 -0
  54. package/dist/internal/frequency-cap.js +84 -0
  55. package/dist/internal/frequency-cap.js.map +1 -0
  56. package/dist/internal/identity.d.ts +14 -0
  57. package/dist/internal/identity.d.ts.map +1 -0
  58. package/dist/internal/identity.js +113 -0
  59. package/dist/internal/identity.js.map +1 -0
  60. package/dist/internal/inapp-matcher.d.ts +13 -0
  61. package/dist/internal/inapp-matcher.d.ts.map +1 -0
  62. package/dist/internal/inapp-matcher.js +65 -0
  63. package/dist/internal/inapp-matcher.js.map +1 -0
  64. package/dist/internal/inapp-rules-cache.d.ts +16 -0
  65. package/dist/internal/inapp-rules-cache.d.ts.map +1 -0
  66. package/dist/internal/inapp-rules-cache.js +88 -0
  67. package/dist/internal/inapp-rules-cache.js.map +1 -0
  68. package/dist/internal/instruction-dedupe.d.ts +16 -0
  69. package/dist/internal/instruction-dedupe.d.ts.map +1 -0
  70. package/dist/internal/instruction-dedupe.js +52 -0
  71. package/dist/internal/instruction-dedupe.js.map +1 -0
  72. package/dist/internal/lifecycle.d.ts +12 -0
  73. package/dist/internal/lifecycle.d.ts.map +1 -0
  74. package/dist/internal/lifecycle.js +97 -0
  75. package/dist/internal/lifecycle.js.map +1 -0
  76. package/dist/internal/modal-coordinator.d.ts +4 -0
  77. package/dist/internal/modal-coordinator.d.ts.map +1 -0
  78. package/dist/internal/modal-coordinator.js +43 -0
  79. package/dist/internal/modal-coordinator.js.map +1 -0
  80. package/dist/internal/modal-queue.d.ts +9 -0
  81. package/dist/internal/modal-queue.d.ts.map +1 -0
  82. package/dist/internal/modal-queue.js +32 -0
  83. package/dist/internal/modal-queue.js.map +1 -0
  84. package/dist/internal/mutation-queue.d.ts +23 -0
  85. package/dist/internal/mutation-queue.d.ts.map +1 -0
  86. package/dist/internal/mutation-queue.js +66 -0
  87. package/dist/internal/mutation-queue.js.map +1 -0
  88. package/dist/internal/prompt-answers.d.ts +6 -0
  89. package/dist/internal/prompt-answers.d.ts.map +1 -0
  90. package/dist/internal/prompt-answers.js +10 -0
  91. package/dist/internal/prompt-answers.js.map +1 -0
  92. package/dist/internal/prompt-flow.d.ts +8 -0
  93. package/dist/internal/prompt-flow.d.ts.map +1 -0
  94. package/dist/internal/prompt-flow.js +26 -0
  95. package/dist/internal/prompt-flow.js.map +1 -0
  96. package/dist/internal/queue.d.ts +17 -0
  97. package/dist/internal/queue.d.ts.map +1 -0
  98. package/dist/internal/queue.js +172 -0
  99. package/dist/internal/queue.js.map +1 -0
  100. package/dist/internal/requests.d.ts +22 -0
  101. package/dist/internal/requests.d.ts.map +1 -0
  102. package/dist/internal/requests.js +146 -0
  103. package/dist/internal/requests.js.map +1 -0
  104. package/dist/internal/rules-cache.d.ts +16 -0
  105. package/dist/internal/rules-cache.d.ts.map +1 -0
  106. package/dist/internal/rules-cache.js +86 -0
  107. package/dist/internal/rules-cache.js.map +1 -0
  108. package/dist/internal/storage.d.ts +36 -0
  109. package/dist/internal/storage.d.ts.map +1 -0
  110. package/dist/internal/storage.js +213 -0
  111. package/dist/internal/storage.js.map +1 -0
  112. package/dist/internal/survey-completion.d.ts +10 -0
  113. package/dist/internal/survey-completion.d.ts.map +1 -0
  114. package/dist/internal/survey-completion.js +11 -0
  115. package/dist/internal/survey-completion.js.map +1 -0
  116. package/dist/internal/survey-matcher.d.ts +21 -0
  117. package/dist/internal/survey-matcher.d.ts.map +1 -0
  118. package/dist/internal/survey-matcher.js +139 -0
  119. package/dist/internal/survey-matcher.js.map +1 -0
  120. package/dist/internal/survey-rules-cache.d.ts +17 -0
  121. package/dist/internal/survey-rules-cache.d.ts.map +1 -0
  122. package/dist/internal/survey-rules-cache.js +91 -0
  123. package/dist/internal/survey-rules-cache.js.map +1 -0
  124. package/dist/internal/survey-store.d.ts +19 -0
  125. package/dist/internal/survey-store.d.ts.map +1 -0
  126. package/dist/internal/survey-store.js +59 -0
  127. package/dist/internal/survey-store.js.map +1 -0
  128. package/dist/internal/transport.d.ts +210 -0
  129. package/dist/internal/transport.d.ts.map +1 -0
  130. package/dist/internal/transport.js +498 -0
  131. package/dist/internal/transport.js.map +1 -0
  132. package/dist/internal/trigger-matcher.d.ts +21 -0
  133. package/dist/internal/trigger-matcher.d.ts.map +1 -0
  134. package/dist/internal/trigger-matcher.js +114 -0
  135. package/dist/internal/trigger-matcher.js.map +1 -0
  136. package/dist/internal/types.d.ts +89 -0
  137. package/dist/internal/types.d.ts.map +1 -0
  138. package/dist/internal/types.js +2 -0
  139. package/dist/internal/types.js.map +1 -0
  140. package/dist/internal/user-state.d.ts +11 -0
  141. package/dist/internal/user-state.d.ts.map +1 -0
  142. package/dist/internal/user-state.js +118 -0
  143. package/dist/internal/user-state.js.map +1 -0
  144. package/dist/native/events.d.ts +27 -0
  145. package/dist/native/events.d.ts.map +1 -0
  146. package/dist/native/events.js +12 -0
  147. package/dist/native/events.js.map +1 -0
  148. package/dist/native/push-bridge.d.ts +20 -0
  149. package/dist/native/push-bridge.d.ts.map +1 -0
  150. package/dist/native/push-bridge.js +92 -0
  151. package/dist/native/push-bridge.js.map +1 -0
  152. package/dist/preview/PromptShell.d.ts +9 -0
  153. package/dist/preview/PromptShell.d.ts.map +1 -0
  154. package/dist/preview/PromptShell.js +128 -0
  155. package/dist/preview/PromptShell.js.map +1 -0
  156. package/dist/preview/SurveyShell.d.ts +15 -0
  157. package/dist/preview/SurveyShell.d.ts.map +1 -0
  158. package/dist/preview/SurveyShell.js +197 -0
  159. package/dist/preview/SurveyShell.js.map +1 -0
  160. package/dist/preview/index.d.ts +4 -0
  161. package/dist/preview/index.d.ts.map +1 -0
  162. package/dist/preview/index.js +16 -0
  163. package/dist/preview/index.js.map +1 -0
  164. package/dist/ui/InAppMessageView.d.ts +12 -0
  165. package/dist/ui/InAppMessageView.d.ts.map +1 -0
  166. package/dist/ui/InAppMessageView.js +260 -0
  167. package/dist/ui/InAppMessageView.js.map +1 -0
  168. package/dist/ui/PromptSheet.d.ts +12 -0
  169. package/dist/ui/PromptSheet.d.ts.map +1 -0
  170. package/dist/ui/PromptSheet.js +285 -0
  171. package/dist/ui/PromptSheet.js.map +1 -0
  172. package/dist/ui/QuestionImageHeader.d.ts +12 -0
  173. package/dist/ui/QuestionImageHeader.d.ts.map +1 -0
  174. package/dist/ui/QuestionImageHeader.js +22 -0
  175. package/dist/ui/QuestionImageHeader.js.map +1 -0
  176. package/dist/ui/SurveyView.d.ts +25 -0
  177. package/dist/ui/SurveyView.d.ts.map +1 -0
  178. package/dist/ui/SurveyView.js +478 -0
  179. package/dist/ui/SurveyView.js.map +1 -0
  180. package/dist/ui/animations.d.ts +4 -0
  181. package/dist/ui/animations.d.ts.map +1 -0
  182. package/dist/ui/animations.js +24 -0
  183. package/dist/ui/animations.js.map +1 -0
  184. package/dist/ui/questions/MultipleChoiceQuestion.d.ts +12 -0
  185. package/dist/ui/questions/MultipleChoiceQuestion.d.ts.map +1 -0
  186. package/dist/ui/questions/MultipleChoiceQuestion.js +41 -0
  187. package/dist/ui/questions/MultipleChoiceQuestion.js.map +1 -0
  188. package/dist/ui/questions/NpsQuestion.d.ts +14 -0
  189. package/dist/ui/questions/NpsQuestion.d.ts.map +1 -0
  190. package/dist/ui/questions/NpsQuestion.js +73 -0
  191. package/dist/ui/questions/NpsQuestion.js.map +1 -0
  192. package/dist/ui/questions/RatingQuestion.d.ts +21 -0
  193. package/dist/ui/questions/RatingQuestion.d.ts.map +1 -0
  194. package/dist/ui/questions/RatingQuestion.js +91 -0
  195. package/dist/ui/questions/RatingQuestion.js.map +1 -0
  196. package/dist/ui/questions/ShortTextQuestion.d.ts +12 -0
  197. package/dist/ui/questions/ShortTextQuestion.d.ts.map +1 -0
  198. package/dist/ui/questions/ShortTextQuestion.js +25 -0
  199. package/dist/ui/questions/ShortTextQuestion.js.map +1 -0
  200. package/dist/ui/requests/BoardView.d.ts +9 -0
  201. package/dist/ui/requests/BoardView.d.ts.map +1 -0
  202. package/dist/ui/requests/BoardView.js +270 -0
  203. package/dist/ui/requests/BoardView.js.map +1 -0
  204. package/dist/ui/requests/CommentsSection.d.ts +7 -0
  205. package/dist/ui/requests/CommentsSection.d.ts.map +1 -0
  206. package/dist/ui/requests/CommentsSection.js +254 -0
  207. package/dist/ui/requests/CommentsSection.js.map +1 -0
  208. package/dist/ui/requests/DetailView.d.ts +8 -0
  209. package/dist/ui/requests/DetailView.d.ts.map +1 -0
  210. package/dist/ui/requests/DetailView.js +206 -0
  211. package/dist/ui/requests/DetailView.js.map +1 -0
  212. package/dist/ui/requests/RequestsHost.d.ts +12 -0
  213. package/dist/ui/requests/RequestsHost.d.ts.map +1 -0
  214. package/dist/ui/requests/RequestsHost.js +58 -0
  215. package/dist/ui/requests/RequestsHost.js.map +1 -0
  216. package/dist/ui/requests/StatusPill.d.ts +6 -0
  217. package/dist/ui/requests/StatusPill.d.ts.map +1 -0
  218. package/dist/ui/requests/StatusPill.js +25 -0
  219. package/dist/ui/requests/StatusPill.js.map +1 -0
  220. package/dist/ui/requests/SubmitView.d.ts +8 -0
  221. package/dist/ui/requests/SubmitView.d.ts.map +1 -0
  222. package/dist/ui/requests/SubmitView.js +94 -0
  223. package/dist/ui/requests/SubmitView.js.map +1 -0
  224. package/dist/ui/requests/shared.d.ts +21 -0
  225. package/dist/ui/requests/shared.d.ts.map +1 -0
  226. package/dist/ui/requests/shared.js +74 -0
  227. package/dist/ui/requests/shared.js.map +1 -0
  228. package/dist/ui/survey-questions.d.ts +20 -0
  229. package/dist/ui/survey-questions.d.ts.map +1 -0
  230. package/dist/ui/survey-questions.js +211 -0
  231. package/dist/ui/survey-questions.js.map +1 -0
  232. package/dist/ui/theme.d.ts +15 -0
  233. package/dist/ui/theme.d.ts.map +1 -0
  234. package/dist/ui/theme.js +31 -0
  235. package/dist/ui/theme.js.map +1 -0
  236. package/ios/Extension/UserGistNotificationService.swift +292 -0
  237. package/ios/UserGistPush.h +16 -0
  238. package/ios/UserGistPush.mm +158 -0
  239. package/ios/UserGistPushImpl.swift +399 -0
  240. package/ios/UserGistPushSwizzle.m +168 -0
  241. package/package.json +89 -0
  242. package/react-native.config.js +16 -0
@@ -0,0 +1,172 @@
1
+ // Bounded, persisted, FIFO event queue.
2
+ // Default: 1000 events / 1 MB cap. Oldest dropped on overflow.
3
+ // Persistence is fire-and-forget; we never block `track()`.
4
+ import { STORAGE_KEYS } from './storage.js';
5
+ import { reportError } from './debug.js';
6
+ const MAX_BYTES = 1_000_000;
7
+ // Bumped every time the persisted shape changes. Older snapshots from
8
+ // previous SDK versions are discarded on hydrate so the SDK never crashes
9
+ // on a deserialise mismatch — events are best-effort, not durable contracts.
10
+ const QUEUE_SCHEMA_VERSION = 2;
11
+ function isPersistedQueue(v) {
12
+ return (typeof v === 'object' &&
13
+ v !== null &&
14
+ typeof v.version === 'number' &&
15
+ Array.isArray(v.events));
16
+ }
17
+ export function createEventQueue(storage, maxSize) {
18
+ let events = [];
19
+ let encodedSizes = [];
20
+ let encodedItemsBytes = 0;
21
+ let hydrated = false;
22
+ let persistTimer = null;
23
+ let persistence = Promise.resolve();
24
+ const overflowListeners = new Set();
25
+ function encodedSize(event) {
26
+ try {
27
+ return JSON.stringify(event).length;
28
+ }
29
+ catch {
30
+ return MAX_BYTES + 1;
31
+ }
32
+ }
33
+ function rebuildSizes() {
34
+ encodedSizes = events.map(encodedSize);
35
+ encodedItemsBytes = encodedSizes.reduce((total, size) => total + size, 0);
36
+ }
37
+ function currentBytes() {
38
+ return 2 + encodedItemsBytes + Math.max(0, events.length - 1);
39
+ }
40
+ function trimOverflow() {
41
+ let dropped = 0;
42
+ while (events.length > 0 && (events.length > maxSize || currentBytes() > MAX_BYTES)) {
43
+ events.shift();
44
+ encodedItemsBytes -= encodedSizes.shift() ?? 0;
45
+ dropped += 1;
46
+ }
47
+ notifyOverflow(dropped);
48
+ return dropped;
49
+ }
50
+ function schedulePersist() {
51
+ if (persistTimer)
52
+ return;
53
+ persistTimer = setTimeout(() => {
54
+ persistTimer = null;
55
+ persistence = persistence.then(persist, persist);
56
+ }, 200);
57
+ }
58
+ async function persist() {
59
+ try {
60
+ trimOverflow();
61
+ const snapshot = events.slice();
62
+ const wrapped = { version: QUEUE_SCHEMA_VERSION, events: snapshot };
63
+ await storage.setJson(STORAGE_KEYS.queue, wrapped);
64
+ }
65
+ catch (e) {
66
+ reportError('queue.persist failed', e);
67
+ }
68
+ }
69
+ function notifyOverflow(dropped) {
70
+ if (dropped <= 0)
71
+ return;
72
+ for (const cb of overflowListeners) {
73
+ try {
74
+ cb(dropped);
75
+ }
76
+ catch (e) {
77
+ reportError('queue overflow listener failed', e);
78
+ }
79
+ }
80
+ }
81
+ return {
82
+ async hydrate() {
83
+ if (hydrated)
84
+ return;
85
+ try {
86
+ const stored = await storage.getJson(STORAGE_KEYS.queue);
87
+ if (isPersistedQueue(stored)) {
88
+ if (stored.version === QUEUE_SCHEMA_VERSION) {
89
+ events = [...stored.events];
90
+ }
91
+ else {
92
+ // Unknown / older schema — discard rather than risk a crash on
93
+ // shape mismatch. Events are best-effort, not durable.
94
+ reportError('queue.hydrate: discarding unknown queue version', stored.version);
95
+ await storage.remove(STORAGE_KEYS.queue);
96
+ }
97
+ }
98
+ else if (Array.isArray(stored)) {
99
+ // Legacy unversioned snapshot from earlier SDK builds. Re-wrap on
100
+ // the next persist() call.
101
+ events = [...stored];
102
+ }
103
+ rebuildSizes();
104
+ if (trimOverflow() > 0)
105
+ schedulePersist();
106
+ }
107
+ catch (e) {
108
+ reportError('queue.hydrate failed', e);
109
+ }
110
+ hydrated = true;
111
+ },
112
+ enqueue(e) {
113
+ events.push(e);
114
+ const size = encodedSize(e);
115
+ encodedSizes.push(size);
116
+ encodedItemsBytes += size;
117
+ trimOverflow();
118
+ schedulePersist();
119
+ },
120
+ peek(n) {
121
+ return events.slice(0, n);
122
+ },
123
+ drop(n) {
124
+ if (n <= 0)
125
+ return;
126
+ const count = Math.min(n, events.length);
127
+ const removedSizes = encodedSizes.splice(0, count);
128
+ events.splice(0, count);
129
+ encodedItemsBytes -= removedSizes.reduce((total, size) => total + size, 0);
130
+ schedulePersist();
131
+ },
132
+ remove(eventIds) {
133
+ if (eventIds.length === 0)
134
+ return;
135
+ const ids = new Set(eventIds);
136
+ events = events.filter((event) => !ids.has(event.eventId));
137
+ rebuildSizes();
138
+ schedulePersist();
139
+ },
140
+ removePurpose(purpose) {
141
+ events = events.filter((event) => event.purpose !== purpose);
142
+ rebuildSizes();
143
+ schedulePersist();
144
+ },
145
+ restore(restored) {
146
+ events = [...restored, ...events];
147
+ rebuildSizes();
148
+ trimOverflow();
149
+ schedulePersist();
150
+ },
151
+ size: () => events.length,
152
+ async clear() {
153
+ events = [];
154
+ encodedSizes = [];
155
+ encodedItemsBytes = 0;
156
+ if (persistTimer) {
157
+ clearTimeout(persistTimer);
158
+ persistTimer = null;
159
+ }
160
+ await persistence;
161
+ await storage.remove(STORAGE_KEYS.queue);
162
+ },
163
+ snapshot: () => events.slice(),
164
+ onOverflow(cb) {
165
+ overflowListeners.add(cb);
166
+ return () => {
167
+ overflowListeners.delete(cb);
168
+ };
169
+ },
170
+ };
171
+ }
172
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/internal/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { Request as RequestDto, RequestVote, RequestFollow } from '@usergist/sdk-core/mobile';
2
+ export interface RequestsCache {
3
+ readonly upsert: (req: RequestDto) => void;
4
+ readonly upsertList: (requests: ReadonlyArray<RequestDto>) => void;
5
+ readonly get: (id: string) => RequestDto | undefined;
6
+ readonly applyOptimisticVote: (id: string, vote: boolean) => () => void;
7
+ readonly applyOptimisticFollow: (id: string, follow: boolean) => () => void;
8
+ readonly commitVote: (id: string, result: RequestVote) => void;
9
+ readonly commitFollow: (id: string, result: RequestFollow) => void;
10
+ readonly subscribe: (cb: (id: string, req: RequestDto) => void) => () => void;
11
+ }
12
+ export declare function createRequestsCache(): RequestsCache;
13
+ /**
14
+ * Debounced search helper for SubmitRequestSheet's typeahead.
15
+ * Cancels prior calls; only the latest result reaches subscribers.
16
+ */
17
+ export declare function createDebouncedSearch<TResult>(fn: (q: string) => Promise<TResult>, delayMs?: number): {
18
+ readonly query: (q: string) => void;
19
+ readonly subscribe: (cb: (q: string, r: TResult) => void) => () => void;
20
+ readonly cancel: () => void;
21
+ };
22
+ //# sourceMappingURL=requests.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.d.ts","sourceRoot":"","sources":["../../src/internal/requests.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,OAAO,IAAI,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAElG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,CAAA;IAC1C,QAAQ,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,KAAK,IAAI,CAAA;IAClE,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,CAAA;IACpD,QAAQ,CAAC,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,MAAM,IAAI,CAAA;IACvE,QAAQ,CAAC,qBAAqB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,KAAK,MAAM,IAAI,CAAA;IAC3E,QAAQ,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;IAC9D,QAAQ,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,KAAK,IAAI,CAAA;IAClE,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;CAC9E;AAED,wBAAgB,mBAAmB,IAAI,aAAa,CA0FnD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAC3C,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,EACnC,OAAO,SAAM,GACZ;IACD,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,QAAQ,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,KAAK,IAAI,KAAK,MAAM,IAAI,CAAA;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAA;CAC5B,CAkCA"}
@@ -0,0 +1,146 @@
1
+ // ============================================================
2
+ // requests cache — optimistic vote/follow with rollback
3
+ // ============================================================
4
+ // Holds an in-memory snapshot of recently-touched requests so the SDK
5
+ // can render counts immediately on tap, then reconcile against the
6
+ // server response. Spec §9 invariants enforced here:
7
+ // - Upvoting auto-creates a follow (followerCount += 1 only if user
8
+ // wasn't already following).
9
+ // - Un-upvoting does NOT remove the follow.
10
+ export function createRequestsCache() {
11
+ const map = new Map();
12
+ const listeners = new Set();
13
+ function notify(id, req) {
14
+ for (const cb of listeners)
15
+ cb(id, req);
16
+ }
17
+ function snapshot(id) {
18
+ return map.get(id);
19
+ }
20
+ return {
21
+ upsert(req) {
22
+ map.set(req.id, req);
23
+ notify(req.id, req);
24
+ },
25
+ upsertList(list) {
26
+ for (const r of list)
27
+ map.set(r.id, r);
28
+ },
29
+ get(id) {
30
+ return map.get(id);
31
+ },
32
+ applyOptimisticVote(id, vote) {
33
+ const before = snapshot(id);
34
+ if (!before)
35
+ return () => { };
36
+ const upvoteDelta = vote && !before.viewerHasUpvoted ? 1 : !vote && before.viewerHasUpvoted ? -1 : 0;
37
+ // Auto-follow: upvoting bumps follower count if user wasn't following.
38
+ const followDelta = vote && !before.viewerIsFollowing ? 1 : 0;
39
+ const next = {
40
+ ...before,
41
+ viewerHasUpvoted: vote,
42
+ viewerIsFollowing: vote ? true : before.viewerIsFollowing,
43
+ upvoteCount: Math.max(0, before.upvoteCount + upvoteDelta),
44
+ followerCount: Math.max(0, before.followerCount + followDelta),
45
+ };
46
+ map.set(id, next);
47
+ notify(id, next);
48
+ return () => {
49
+ map.set(id, before);
50
+ notify(id, before);
51
+ };
52
+ },
53
+ applyOptimisticFollow(id, follow) {
54
+ const before = snapshot(id);
55
+ if (!before)
56
+ return () => { };
57
+ const delta = follow && !before.viewerIsFollowing ? 1 : !follow && before.viewerIsFollowing ? -1 : 0;
58
+ const next = {
59
+ ...before,
60
+ viewerIsFollowing: follow,
61
+ followerCount: Math.max(0, before.followerCount + delta),
62
+ };
63
+ map.set(id, next);
64
+ notify(id, next);
65
+ return () => {
66
+ map.set(id, before);
67
+ notify(id, before);
68
+ };
69
+ },
70
+ commitVote(id, result) {
71
+ const before = snapshot(id);
72
+ if (!before)
73
+ return;
74
+ const next = {
75
+ ...before,
76
+ viewerHasUpvoted: result.upvoted,
77
+ viewerIsFollowing: result.followed,
78
+ upvoteCount: result.upvoteCount,
79
+ followerCount: result.followerCount,
80
+ };
81
+ map.set(id, next);
82
+ notify(id, next);
83
+ },
84
+ commitFollow(id, result) {
85
+ const before = snapshot(id);
86
+ if (!before)
87
+ return;
88
+ const next = {
89
+ ...before,
90
+ viewerIsFollowing: result.following,
91
+ followerCount: result.followerCount,
92
+ };
93
+ map.set(id, next);
94
+ notify(id, next);
95
+ },
96
+ subscribe(cb) {
97
+ listeners.add(cb);
98
+ return () => {
99
+ listeners.delete(cb);
100
+ };
101
+ },
102
+ };
103
+ }
104
+ /**
105
+ * Debounced search helper for SubmitRequestSheet's typeahead.
106
+ * Cancels prior calls; only the latest result reaches subscribers.
107
+ */
108
+ export function createDebouncedSearch(fn, delayMs = 300) {
109
+ let timer = null;
110
+ let lastSeq = 0;
111
+ const listeners = new Set();
112
+ return {
113
+ query(q) {
114
+ if (timer)
115
+ clearTimeout(timer);
116
+ const seq = ++lastSeq;
117
+ timer = setTimeout(() => {
118
+ void (async () => {
119
+ try {
120
+ const r = await fn(q);
121
+ if (seq === lastSeq) {
122
+ for (const cb of listeners)
123
+ cb(q, r);
124
+ }
125
+ }
126
+ catch {
127
+ // Swallow — typeahead errors don't surface; SubmitRequestSheet
128
+ // simply renders nothing and lets the user "post anyway".
129
+ }
130
+ })();
131
+ }, delayMs);
132
+ },
133
+ subscribe(cb) {
134
+ listeners.add(cb);
135
+ return () => {
136
+ listeners.delete(cb);
137
+ };
138
+ },
139
+ cancel() {
140
+ if (timer)
141
+ clearTimeout(timer);
142
+ lastSeq++;
143
+ },
144
+ };
145
+ }
146
+ //# sourceMappingURL=requests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requests.js","sourceRoot":"","sources":["../../src/internal/requests.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ArmedTrigger } from '@usergist/sdk-core/mobile';
2
+ import { type StorageScope } from './storage.js';
3
+ import type { Transport } from './transport.js';
4
+ export interface RulesCache {
5
+ readonly hydrate: () => Promise<void>;
6
+ readonly refresh: (params: {
7
+ readonly anonymousId: string;
8
+ readonly externalId: string | null;
9
+ readonly force?: boolean;
10
+ }) => Promise<ReadonlyArray<ArmedTrigger>>;
11
+ readonly getForEvent: (eventName: string) => ReadonlyArray<ArmedTrigger>;
12
+ readonly all: () => ReadonlyArray<ArmedTrigger>;
13
+ readonly clear: () => Promise<void>;
14
+ }
15
+ export declare function createRulesCache(storage: StorageScope, transport: Transport, defaultSyncMs: number): RulesCache;
16
+ //# sourceMappingURL=rules-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-cache.d.ts","sourceRoot":"","sources":["../../src/internal/rules-cache.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,EAAgB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAA;AAE9D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG/C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE;QACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;QAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;QAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KACzB,KAAK,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAA;IAC1C,QAAQ,CAAC,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,aAAa,CAAC,YAAY,CAAC,CAAA;IACxE,QAAQ,CAAC,GAAG,EAAE,MAAM,aAAa,CAAC,YAAY,CAAC,CAAA;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACpC;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,SAAS,EACpB,aAAa,EAAE,MAAM,GACpB,UAAU,CA0EZ"}
@@ -0,0 +1,86 @@
1
+ // Armed-triggers cache.
2
+ // - Pulled on app foreground, every 5 min while foregrounded, and on-demand.
3
+ // - Persisted to AsyncStorage.
4
+ // - The matcher reads from here synchronously (no I/O on track()).
5
+ import { STORAGE_KEYS } from './storage.js';
6
+ import { reportError, debugLog } from './debug.js';
7
+ export function createRulesCache(storage, transport, defaultSyncMs) {
8
+ let triggers = [];
9
+ let byEvent = {};
10
+ let fetchedAt = 0;
11
+ let hydrated = false;
12
+ let inflight = null;
13
+ function indexByEvent(list) {
14
+ const map = {};
15
+ for (const t of list) {
16
+ const bucket = map[t.eventName] ?? [];
17
+ bucket.push(t);
18
+ map[t.eventName] = bucket;
19
+ }
20
+ // freeze arrays
21
+ const out = {};
22
+ for (const k of Object.keys(map))
23
+ out[k] = map[k] ?? [];
24
+ return out;
25
+ }
26
+ return {
27
+ async hydrate() {
28
+ if (hydrated)
29
+ return;
30
+ try {
31
+ const stored = await storage.getJson(STORAGE_KEYS.rulesCache);
32
+ if (stored?.triggers) {
33
+ triggers = stored.triggers;
34
+ byEvent = indexByEvent(triggers);
35
+ fetchedAt = Date.parse(stored.fetchedAt);
36
+ }
37
+ }
38
+ catch (e) {
39
+ reportError('rulesCache.hydrate failed', e);
40
+ }
41
+ hydrated = true;
42
+ },
43
+ async refresh({ anonymousId, externalId, force }) {
44
+ const now = Date.now();
45
+ if (!force && now - fetchedAt < defaultSyncMs && triggers.length > 0) {
46
+ return triggers;
47
+ }
48
+ if (inflight)
49
+ return inflight;
50
+ inflight = (async () => {
51
+ try {
52
+ const res = await transport.armedTriggers({ anonymousId, externalId });
53
+ triggers = res.triggers;
54
+ byEvent = indexByEvent(triggers);
55
+ fetchedAt = Date.now();
56
+ const cache = {
57
+ triggers,
58
+ fetchedAt: new Date(fetchedAt).toISOString(),
59
+ serverTime: res.serverTime,
60
+ nextSyncMs: res.nextSyncMs,
61
+ };
62
+ await storage.setJson(STORAGE_KEYS.rulesCache, cache);
63
+ debugLog('rulesCache refreshed', { count: triggers.length });
64
+ return triggers;
65
+ }
66
+ catch (e) {
67
+ reportError('rulesCache.refresh failed', e);
68
+ return triggers;
69
+ }
70
+ finally {
71
+ inflight = null;
72
+ }
73
+ })();
74
+ return inflight;
75
+ },
76
+ getForEvent: (eventName) => byEvent[eventName] ?? [],
77
+ all: () => triggers,
78
+ async clear() {
79
+ triggers = [];
80
+ byEvent = {};
81
+ fetchedAt = 0;
82
+ await storage.remove(STORAGE_KEYS.rulesCache);
83
+ },
84
+ };
85
+ }
86
+ //# sourceMappingURL=rules-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules-cache.js","sourceRoot":"","sources":["../../src/internal/rules-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ export interface UserGistStorageAdapter {
2
+ readonly getItem: (k: string) => Promise<string | null>;
3
+ readonly setItem: (k: string, v: string) => Promise<void>;
4
+ readonly removeItem: (k: string) => Promise<void>;
5
+ readonly multiRemove?: (keys: ReadonlyArray<string>) => Promise<void>;
6
+ }
7
+ /** Configure a host-owned encrypted key/value backend before `init()`. */
8
+ export declare function configureStorageAdapter(adapter: UserGistStorageAdapter): void;
9
+ export interface StorageScope {
10
+ readonly key: (suffix: string) => string;
11
+ readonly getJson: <T>(suffix: string) => Promise<T | null>;
12
+ readonly setJson: <T>(suffix: string, value: T) => Promise<void>;
13
+ readonly setJsonStrict: <T>(suffix: string, value: T) => Promise<void>;
14
+ readonly remove: (suffix: string) => Promise<void>;
15
+ readonly clearAll: (suffixes: ReadonlyArray<string>) => Promise<void>;
16
+ }
17
+ export declare function createStorageScope(writeKey: string): StorageScope;
18
+ export declare const STORAGE_KEYS: {
19
+ readonly identity: "identity";
20
+ readonly consent: "consent";
21
+ readonly queue: "queue";
22
+ readonly rulesCache: "rulesCache";
23
+ readonly surveyRulesCache: "surveyRulesCache";
24
+ readonly inAppRulesCache: "inAppRulesCache";
25
+ readonly frequencyCaps: "frequencyCaps";
26
+ readonly userProperties: "userProperties";
27
+ readonly eventHistory: "eventHistory";
28
+ readonly subjectToken: "subjectToken";
29
+ readonly mutationQueue: "mutationQueue";
30
+ readonly instructionCursor: "instructionCursor";
31
+ readonly seenInstructions: "seenInstructions";
32
+ readonly localInstructionDedupe: "localInstructionDedupe";
33
+ readonly appVersion: "appVersion";
34
+ };
35
+ export type StorageKey = (typeof STORAGE_KEYS)[keyof typeof STORAGE_KEYS];
36
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/internal/storage.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACvD,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACzD,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtE;AAeD,0EAA0E;AAC1E,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAE7E;AAoGD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAA;IACxC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IAC1D,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAChE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtE,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAClD,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtE;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAgFjE;AAED,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;CAgBf,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAA"}