@chipmobilesdk/rn-core 0.1.0 → 0.2.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 (158) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/lib/commonjs/diagnostics/index.js +81 -0
  3. package/lib/commonjs/diagnostics/index.js.map +1 -0
  4. package/lib/commonjs/errors/index.js +86 -0
  5. package/lib/commonjs/errors/index.js.map +1 -0
  6. package/lib/commonjs/index.js +305 -0
  7. package/lib/commonjs/index.js.map +1 -0
  8. package/lib/commonjs/intl/index.js +98 -0
  9. package/lib/commonjs/intl/index.js.map +1 -0
  10. package/lib/commonjs/kv/index.js +83 -0
  11. package/lib/commonjs/kv/index.js.map +1 -0
  12. package/lib/commonjs/lazy/index.js +63 -0
  13. package/lib/commonjs/lazy/index.js.map +1 -0
  14. package/lib/commonjs/listeners/index.js +110 -0
  15. package/lib/commonjs/listeners/index.js.map +1 -0
  16. package/lib/commonjs/messages/index.js +53 -0
  17. package/lib/commonjs/messages/index.js.map +1 -0
  18. package/lib/commonjs/package.json +1 -0
  19. package/lib/commonjs/react/index.js +93 -0
  20. package/lib/commonjs/react/index.js.map +1 -0
  21. package/lib/commonjs/redact/index.js +128 -0
  22. package/lib/commonjs/redact/index.js.map +1 -0
  23. package/lib/commonjs/runtime/index.js +77 -0
  24. package/lib/commonjs/runtime/index.js.map +1 -0
  25. package/lib/commonjs/runtime/lifecycle.js +105 -0
  26. package/lib/commonjs/runtime/lifecycle.js.map +1 -0
  27. package/lib/commonjs/scheduler/index.js +216 -0
  28. package/lib/commonjs/scheduler/index.js.map +1 -0
  29. package/lib/commonjs/store/index.js +39 -0
  30. package/lib/commonjs/store/index.js.map +1 -0
  31. package/lib/commonjs/testing/conformance.js +79 -0
  32. package/lib/commonjs/testing/conformance.js.map +1 -0
  33. package/lib/commonjs/testing/index.js +58 -0
  34. package/lib/commonjs/testing/index.js.map +1 -0
  35. package/lib/commonjs/testing/lifecycle.js +37 -0
  36. package/lib/commonjs/testing/lifecycle.js.map +1 -0
  37. package/lib/commonjs/testing/redaction.js +118 -0
  38. package/lib/commonjs/testing/redaction.js.map +1 -0
  39. package/lib/commonjs/testing/scheduler.js +51 -0
  40. package/lib/commonjs/testing/scheduler.js.map +1 -0
  41. package/lib/module/diagnostics/index.js +75 -0
  42. package/lib/module/diagnostics/index.js.map +1 -0
  43. package/lib/module/errors/index.js +78 -0
  44. package/lib/module/errors/index.js.map +1 -0
  45. package/lib/module/index.js +24 -0
  46. package/lib/module/index.js.map +1 -0
  47. package/lib/module/intl/index.js +91 -0
  48. package/lib/module/intl/index.js.map +1 -0
  49. package/lib/module/kv/index.js +76 -0
  50. package/lib/module/kv/index.js.map +1 -0
  51. package/lib/module/lazy/index.js +59 -0
  52. package/lib/module/lazy/index.js.map +1 -0
  53. package/lib/module/listeners/index.js +104 -0
  54. package/lib/module/listeners/index.js.map +1 -0
  55. package/lib/module/messages/index.js +48 -0
  56. package/lib/module/messages/index.js.map +1 -0
  57. package/lib/module/package.json +1 -0
  58. package/lib/module/react/index.js +86 -0
  59. package/lib/module/react/index.js.map +1 -0
  60. package/lib/module/redact/index.js +118 -0
  61. package/lib/module/redact/index.js.map +1 -0
  62. package/lib/module/runtime/index.js +52 -0
  63. package/lib/module/runtime/index.js.map +1 -0
  64. package/lib/module/runtime/lifecycle.js +99 -0
  65. package/lib/module/runtime/lifecycle.js.map +1 -0
  66. package/lib/module/scheduler/index.js +203 -0
  67. package/lib/module/scheduler/index.js.map +1 -0
  68. package/lib/module/store/index.js +33 -0
  69. package/lib/module/store/index.js.map +1 -0
  70. package/lib/module/testing/conformance.js +72 -0
  71. package/lib/module/testing/conformance.js.map +1 -0
  72. package/lib/module/testing/index.js +12 -0
  73. package/lib/module/testing/index.js.map +1 -0
  74. package/lib/module/testing/lifecycle.js +32 -0
  75. package/lib/module/testing/lifecycle.js.map +1 -0
  76. package/lib/module/testing/redaction.js +113 -0
  77. package/lib/module/testing/redaction.js.map +1 -0
  78. package/lib/module/testing/scheduler.js +47 -0
  79. package/lib/module/testing/scheduler.js.map +1 -0
  80. package/lib/typescript/commonjs/diagnostics/index.d.ts +49 -0
  81. package/lib/typescript/commonjs/diagnostics/index.d.ts.map +1 -0
  82. package/lib/typescript/commonjs/errors/index.d.ts +59 -0
  83. package/lib/typescript/commonjs/errors/index.d.ts.map +1 -0
  84. package/lib/typescript/commonjs/index.d.ts +22 -0
  85. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  86. package/lib/typescript/commonjs/intl/index.d.ts +25 -0
  87. package/lib/typescript/commonjs/intl/index.d.ts.map +1 -0
  88. package/lib/typescript/commonjs/kv/index.d.ts +38 -0
  89. package/lib/typescript/commonjs/kv/index.d.ts.map +1 -0
  90. package/lib/typescript/commonjs/lazy/index.d.ts +36 -0
  91. package/lib/typescript/commonjs/lazy/index.d.ts.map +1 -0
  92. package/lib/typescript/commonjs/listeners/index.d.ts +61 -0
  93. package/lib/typescript/commonjs/listeners/index.d.ts.map +1 -0
  94. package/lib/typescript/commonjs/messages/index.d.ts +39 -0
  95. package/lib/typescript/commonjs/messages/index.d.ts.map +1 -0
  96. package/lib/typescript/commonjs/package.json +1 -0
  97. package/lib/typescript/commonjs/react/index.d.ts +38 -0
  98. package/lib/typescript/commonjs/react/index.d.ts.map +1 -0
  99. package/lib/typescript/commonjs/redact/index.d.ts +47 -0
  100. package/lib/typescript/commonjs/redact/index.d.ts.map +1 -0
  101. package/lib/typescript/commonjs/runtime/index.d.ts +21 -0
  102. package/lib/typescript/commonjs/runtime/index.d.ts.map +1 -0
  103. package/lib/typescript/commonjs/runtime/lifecycle.d.ts +34 -0
  104. package/lib/typescript/commonjs/runtime/lifecycle.d.ts.map +1 -0
  105. package/lib/typescript/commonjs/scheduler/index.d.ts +108 -0
  106. package/lib/typescript/commonjs/scheduler/index.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/store/index.d.ts +18 -0
  108. package/lib/typescript/commonjs/store/index.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/testing/conformance.d.ts +35 -0
  110. package/lib/typescript/commonjs/testing/conformance.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/testing/index.d.ts +10 -0
  112. package/lib/typescript/commonjs/testing/index.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/testing/lifecycle.d.ts +15 -0
  114. package/lib/typescript/commonjs/testing/lifecycle.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/testing/redaction.d.ts +35 -0
  116. package/lib/typescript/commonjs/testing/redaction.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/testing/scheduler.d.ts +15 -0
  118. package/lib/typescript/commonjs/testing/scheduler.d.ts.map +1 -0
  119. package/lib/typescript/module/diagnostics/index.d.ts +49 -0
  120. package/lib/typescript/module/diagnostics/index.d.ts.map +1 -0
  121. package/lib/typescript/module/errors/index.d.ts +59 -0
  122. package/lib/typescript/module/errors/index.d.ts.map +1 -0
  123. package/lib/typescript/module/index.d.ts +22 -0
  124. package/lib/typescript/module/index.d.ts.map +1 -0
  125. package/lib/typescript/module/intl/index.d.ts +25 -0
  126. package/lib/typescript/module/intl/index.d.ts.map +1 -0
  127. package/lib/typescript/module/kv/index.d.ts +38 -0
  128. package/lib/typescript/module/kv/index.d.ts.map +1 -0
  129. package/lib/typescript/module/lazy/index.d.ts +36 -0
  130. package/lib/typescript/module/lazy/index.d.ts.map +1 -0
  131. package/lib/typescript/module/listeners/index.d.ts +61 -0
  132. package/lib/typescript/module/listeners/index.d.ts.map +1 -0
  133. package/lib/typescript/module/messages/index.d.ts +39 -0
  134. package/lib/typescript/module/messages/index.d.ts.map +1 -0
  135. package/lib/typescript/module/package.json +1 -0
  136. package/lib/typescript/module/react/index.d.ts +38 -0
  137. package/lib/typescript/module/react/index.d.ts.map +1 -0
  138. package/lib/typescript/module/redact/index.d.ts +47 -0
  139. package/lib/typescript/module/redact/index.d.ts.map +1 -0
  140. package/lib/typescript/module/runtime/index.d.ts +21 -0
  141. package/lib/typescript/module/runtime/index.d.ts.map +1 -0
  142. package/lib/typescript/module/runtime/lifecycle.d.ts +34 -0
  143. package/lib/typescript/module/runtime/lifecycle.d.ts.map +1 -0
  144. package/lib/typescript/module/scheduler/index.d.ts +108 -0
  145. package/lib/typescript/module/scheduler/index.d.ts.map +1 -0
  146. package/lib/typescript/module/store/index.d.ts +18 -0
  147. package/lib/typescript/module/store/index.d.ts.map +1 -0
  148. package/lib/typescript/module/testing/conformance.d.ts +35 -0
  149. package/lib/typescript/module/testing/conformance.d.ts.map +1 -0
  150. package/lib/typescript/module/testing/index.d.ts +10 -0
  151. package/lib/typescript/module/testing/index.d.ts.map +1 -0
  152. package/lib/typescript/module/testing/lifecycle.d.ts +15 -0
  153. package/lib/typescript/module/testing/lifecycle.d.ts.map +1 -0
  154. package/lib/typescript/module/testing/redaction.d.ts +35 -0
  155. package/lib/typescript/module/testing/redaction.d.ts.map +1 -0
  156. package/lib/typescript/module/testing/scheduler.d.ts +15 -0
  157. package/lib/typescript/module/testing/scheduler.d.ts.map +1 -0
  158. package/package.json +154 -46
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Time, retries, concurrency and bounds, shared by every package (CORE-04,
5
+ * CORE-05).
6
+ *
7
+ * rn-ads and rn-payment each had their own copy of these, and the copies had
8
+ * drifted: one validated a backoff and the other did not, one reported a retry
9
+ * policy out of bounds under a timeout's error code. Packages keep their domain
10
+ * defaults and bounds; the mechanism lives here, and bounds checks take a `fail`
11
+ * callback so each package raises its own error with its own code.
12
+ */
13
+ import { reportAsynchronously } from "../listeners/index.js";
14
+
15
+ /**
16
+ * How timers are scheduled. Injectable so a test drives backoff and expiry by
17
+ * moving a clock instead of waiting.
18
+ */
19
+
20
+ export const realScheduler = {
21
+ setTimeout: (callback, ms) => setTimeout(callback, ms),
22
+ clearTimeout: handle => clearTimeout(handle)
23
+ };
24
+
25
+ /**
26
+ * Every timer an owner started, so disposing it can prove nothing is left: a
27
+ * leaked timer is otherwise invisible until it fires into a disposed consumer.
28
+ */
29
+
30
+ export function createTimerSet(scheduler = realScheduler) {
31
+ const handles = new Set();
32
+ return {
33
+ after(ms, callback) {
34
+ const handle = scheduler.setTimeout(() => {
35
+ handles.delete(handle);
36
+ callback();
37
+ }, ms);
38
+ handles.add(handle);
39
+ let cleared = false;
40
+ return () => {
41
+ if (cleared) return;
42
+ cleared = true;
43
+ scheduler.clearTimeout(handle);
44
+ handles.delete(handle);
45
+ };
46
+ },
47
+ clearAll() {
48
+ for (const handle of handles) scheduler.clearTimeout(handle);
49
+ handles.clear();
50
+ },
51
+ size: () => handles.size
52
+ };
53
+ }
54
+ /** Delay before `attempt`, 1-based: initial × factor^(attempt−1), capped, maybe jittered. */
55
+ export function computeBackoff(attempt, spec, random = Math.random) {
56
+ const raw = spec.initialDelayMs * Math.pow(spec.factor ?? 2, Math.max(0, attempt - 1));
57
+ const capped = Math.min(raw, spec.maxDelayMs);
58
+ return spec.jitter === 'full' ? Math.floor(capped * random()) : capped;
59
+ }
60
+ /** Runs `attempt` now, then on the backoff schedule until it succeeds, is cancelled or runs out. */
61
+ export function runWithRetry(options) {
62
+ const {
63
+ spec,
64
+ attempt,
65
+ onExhausted
66
+ } = options;
67
+ const scheduler = options.scheduler ?? realScheduler;
68
+ const random = options.random ?? Math.random;
69
+ let count = 0;
70
+ let cancelled = false;
71
+ let pending;
72
+ const run = async () => {
73
+ if (cancelled) return;
74
+ count += 1;
75
+ let succeeded = false;
76
+ try {
77
+ succeeded = await attempt(count);
78
+ } catch {
79
+ // A throwing attempt is a failed attempt; letting it escape would
80
+ // abandon the schedule.
81
+ succeeded = false;
82
+ }
83
+ if (cancelled || succeeded) return;
84
+ if (count >= spec.maxAttempts) {
85
+ onExhausted?.(count);
86
+ return;
87
+ }
88
+ pending = scheduler.setTimeout(() => {
89
+ pending = undefined;
90
+ start();
91
+ }, computeBackoff(count + 1, spec, random));
92
+ };
93
+ // Only `onExhausted` can throw past `run`; that is reported, not swallowed.
94
+ const start = () => {
95
+ run().catch(reportAsynchronously);
96
+ };
97
+ start();
98
+ return {
99
+ cancel() {
100
+ cancelled = true;
101
+ if (pending !== undefined) {
102
+ scheduler.clearTimeout(pending);
103
+ pending = undefined;
104
+ }
105
+ },
106
+ attempts: () => count,
107
+ exhausted: () => count >= spec.maxAttempts
108
+ };
109
+ }
110
+
111
+ /**
112
+ * Joins concurrent callers onto one in-flight operation. Once it settles the
113
+ * slot clears, so a later call starts fresh: de-duplication, not caching.
114
+ */
115
+ export function createSingleFlight() {
116
+ let current;
117
+ return {
118
+ run(operation) {
119
+ if (current) return current;
120
+ const flight = operation().finally(() => {
121
+ if (current === flight) current = undefined;
122
+ });
123
+ current = flight;
124
+ return flight;
125
+ },
126
+ inFlight: () => current !== undefined
127
+ };
128
+ }
129
+
130
+ /** Distinguishes "refused because busy" from any other failure, without throwing. */
131
+
132
+ /** Admits one operation at a time and refuses the rest, rather than queueing them. */
133
+ export function createExclusive() {
134
+ let held = false;
135
+ return {
136
+ async run(operation) {
137
+ if (held) return {
138
+ acquired: false
139
+ };
140
+ held = true;
141
+ try {
142
+ return {
143
+ acquired: true,
144
+ value: await operation()
145
+ };
146
+ } finally {
147
+ held = false;
148
+ }
149
+ },
150
+ busy: () => held
151
+ };
152
+ }
153
+
154
+ /** Admits at most one call per `minIntervalMs`; a refused call is dropped, not deferred. */
155
+ export function createRateLimiter(minIntervalMs, now = Date.now) {
156
+ let lastAt;
157
+ return {
158
+ tryAcquire() {
159
+ const at = now();
160
+ if (lastAt !== undefined && at - lastAt < minIntervalMs) return false;
161
+ lastAt = at;
162
+ return true;
163
+ },
164
+ reset() {
165
+ lastAt = undefined;
166
+ }
167
+ };
168
+ }
169
+
170
+ /**
171
+ * Rejects with `onTimeout()` after `ms`. Always clears its timer, including when
172
+ * the promise wins, so no operation leaks one.
173
+ */
174
+ export function withTimeout(promise, ms, onTimeout, scheduler = realScheduler) {
175
+ let timer;
176
+ const timeout = new Promise((_, reject) => {
177
+ timer = scheduler.setTimeout(() => reject(onTimeout()), ms);
178
+ });
179
+ return Promise.race([promise, timeout]).finally(() => {
180
+ if (timer !== undefined) scheduler.clearTimeout(timer);
181
+ });
182
+ }
183
+ /**
184
+ * `value` when it is a finite number inside `range`; otherwise throws what `fail`
185
+ * builds. Out-of-range values are rejected, never clamped: clamping tells an app
186
+ * it configured something it did not.
187
+ */
188
+ export function checkRange(label, value, range, fail, unit = '') {
189
+ if (!Number.isFinite(value) || value < range.min || value > range.max) {
190
+ throw fail(`${label} must be between ${range.min}${unit} and ${range.max}${unit}; received ${value}`);
191
+ }
192
+ return value;
193
+ }
194
+
195
+ /** As `checkRange`, and a whole number. */
196
+ export function checkInteger(label, value, range, fail) {
197
+ checkRange(label, value, range, fail);
198
+ if (!Number.isInteger(value)) {
199
+ throw fail(`${label} must be a whole number; received ${value}`);
200
+ }
201
+ return value;
202
+ }
203
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["reportAsynchronously","realScheduler","setTimeout","callback","ms","clearTimeout","handle","createTimerSet","scheduler","handles","Set","after","delete","add","cleared","clearAll","clear","size","computeBackoff","attempt","spec","random","Math","raw","initialDelayMs","pow","factor","max","capped","min","maxDelayMs","jitter","floor","runWithRetry","options","onExhausted","count","cancelled","pending","run","succeeded","maxAttempts","undefined","start","catch","cancel","attempts","exhausted","createSingleFlight","current","operation","flight","finally","inFlight","createExclusive","held","acquired","value","busy","createRateLimiter","minIntervalMs","now","Date","lastAt","tryAcquire","at","reset","withTimeout","promise","onTimeout","timer","timeout","Promise","_","reject","race","checkRange","label","range","fail","unit","Number","isFinite","checkInteger","isInteger"],"sourceRoot":"../../../src","sources":["scheduler/index.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * A store whose snapshot keeps its identity until the state actually changes,
5
+ * which is what `useSyncExternalStore` needs (CORE-07). No React here: a package's
6
+ * pure core can hold its state in one, and its hooks read it through
7
+ * `@chipmobilesdk/rn-core/react`.
8
+ */
9
+ import { createListenerSet } from "../listeners/index.js";
10
+ export function createStore(initial, isEqual = Object.is) {
11
+ let snapshot = initial;
12
+ const listeners = createListenerSet();
13
+ return {
14
+ getSnapshot: () => snapshot,
15
+ setState(next) {
16
+ const value = typeof next === 'function' ? next(snapshot) : next;
17
+ if (isEqual(snapshot, value)) return;
18
+ snapshot = value;
19
+ listeners.notify();
20
+ },
21
+ subscribe: listener => listeners.add(listener)
22
+ };
23
+ }
24
+
25
+ /** Same keys, and each value `Object.is` the other's. */
26
+ export function shallowEqual(a, b) {
27
+ if (Object.is(a, b)) return true;
28
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;
29
+ const keysA = Object.keys(a);
30
+ if (keysA.length !== Object.keys(b).length) return false;
31
+ return keysA.every(key => Object.prototype.hasOwnProperty.call(b, key) && Object.is(a[key], b[key]));
32
+ }
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createListenerSet","createStore","initial","isEqual","Object","is","snapshot","listeners","getSnapshot","setState","next","value","notify","subscribe","listener","add","shallowEqual","a","b","keysA","keys","length","every","key","prototype","hasOwnProperty","call"],"sourceRoot":"../../../src","sources":["store/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,iBAAiB,QAA0B,uBAAc;AAUlE,OAAO,SAASC,WAAWA,CAAIC,OAAU,EAAEC,OAAgC,GAAGC,MAAM,CAACC,EAAE,EAAY;EAClG,IAAIC,QAAQ,GAAGJ,OAAO;EACtB,MAAMK,SAAS,GAAGP,iBAAiB,CAAK,CAAC;EACzC,OAAO;IACNQ,WAAW,EAAEA,CAAA,KAAMF,QAAQ;IAC3BG,QAAQA,CAACC,IAAI,EAAE;MACd,MAAMC,KAAK,GAAG,OAAOD,IAAI,KAAK,UAAU,GAAIA,IAAI,CAAwBJ,QAAQ,CAAC,GAAGI,IAAI;MACxF,IAAIP,OAAO,CAACG,QAAQ,EAAEK,KAAK,CAAC,EAAE;MAC9BL,QAAQ,GAAGK,KAAK;MAChBJ,SAAS,CAACK,MAAM,CAAC,CAAC;IACnB,CAAC;IACDC,SAAS,EAAEC,QAAQ,IAAIP,SAAS,CAACQ,GAAG,CAACD,QAAQ;EAC9C,CAAC;AACF;;AAEA;AACA,OAAO,SAASE,YAAYA,CAAIC,CAAI,EAAEC,CAAI,EAAW;EACpD,IAAId,MAAM,CAACC,EAAE,CAACY,CAAC,EAAEC,CAAC,CAAC,EAAE,OAAO,IAAI;EAChC,IAAI,OAAOD,CAAC,KAAK,QAAQ,IAAI,OAAOC,CAAC,KAAK,QAAQ,IAAID,CAAC,KAAK,IAAI,IAAIC,CAAC,KAAK,IAAI,EAAE,OAAO,KAAK;EAC5F,MAAMC,KAAK,GAAGf,MAAM,CAACgB,IAAI,CAACH,CAAC,CAAC;EAC5B,IAAIE,KAAK,CAACE,MAAM,KAAKjB,MAAM,CAACgB,IAAI,CAACF,CAAC,CAAC,CAACG,MAAM,EAAE,OAAO,KAAK;EACxD,OAAOF,KAAK,CAACG,KAAK,CACjBC,GAAG,IACFnB,MAAM,CAACoB,SAAS,CAACC,cAAc,CAACC,IAAI,CAACR,CAAC,EAAEK,GAAG,CAAC,IAC5CnB,MAAM,CAACC,EAAE,CAAEY,CAAC,CAA6BM,GAAG,CAAC,EAAGL,CAAC,CAA6BK,GAAG,CAAC,CACpF,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * A conformance harness that runs in Jest and on a device alike (CORE-13, IOS-12).
5
+ *
6
+ * A package describes what any implementation of one of its ports must do as a
7
+ * list of checks. The same list runs against the fake its tests use and against
8
+ * the real adapter (with the native module mocked in Jest, or for real in a demo
9
+ * screen), so the fake cannot drift from the adapter it stands in for. A report
10
+ * is plain data; `expectConformance` turns a failing one into a Jest failure.
11
+ */
12
+
13
+ /** Runs every check against a fresh subject, so no check depends on another's leftovers. */
14
+ export async function runChecks(makeSubject, checks) {
15
+ const failures = [];
16
+ for (const check of checks) {
17
+ try {
18
+ await check.run(await makeSubject());
19
+ } catch (error) {
20
+ failures.push({
21
+ check: check.name,
22
+ detail: error instanceof Error ? error.message : String(error)
23
+ });
24
+ }
25
+ }
26
+ return {
27
+ passed: failures.length === 0,
28
+ checks: checks.length,
29
+ failures
30
+ };
31
+ }
32
+
33
+ /** Throws one error listing every failed check, for a test runner to report. */
34
+ export function expectConformance(report, subject = 'implementation') {
35
+ if (report.passed) return;
36
+ const lines = report.failures.map(failure => ` - ${failure.check}: ${failure.detail}`);
37
+ throw new Error(`${subject} failed ${report.failures.length} of ${report.checks} checks:\n${lines.join('\n')}`);
38
+ }
39
+
40
+ /** A failed expectation inside a check. */
41
+ export function ensure(condition, message) {
42
+ if (!condition) throw new Error(message);
43
+ }
44
+ /**
45
+ * Deterministic fault injection: a fake or an adapter calls `throwIfFaulted` at its
46
+ * named points, and a test arms the ones it wants to fail (CORE-13, NOT-22).
47
+ */
48
+ export function createFaultRegistry() {
49
+ const armed = new Map();
50
+ const fired = new Set();
51
+ return {
52
+ arm(point, fault, times = 1) {
53
+ armed.set(point, {
54
+ fault,
55
+ remaining: times
56
+ });
57
+ },
58
+ disarm(point) {
59
+ if (point === undefined) armed.clear();else armed.delete(point);
60
+ },
61
+ throwIfFaulted(point) {
62
+ const entry = armed.get(point);
63
+ if (!entry) return;
64
+ entry.remaining -= 1;
65
+ if (entry.remaining <= 0) armed.delete(point);
66
+ fired.add(point);
67
+ throw entry.fault();
68
+ },
69
+ fired: () => [...fired]
70
+ };
71
+ }
72
+ //# sourceMappingURL=conformance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["runChecks","makeSubject","checks","failures","check","run","error","push","name","detail","Error","message","String","passed","length","expectConformance","report","subject","lines","map","failure","join","ensure","condition","createFaultRegistry","armed","Map","fired","Set","arm","point","fault","times","set","remaining","disarm","undefined","clear","delete","throwIfFaulted","entry","get","add"],"sourceRoot":"../../../src","sources":["testing/conformance.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAQA;AACA,OAAO,eAAeA,SAASA,CAC9BC,WAA6C,EAC7CC,MAAiC,EACJ;EAC7B,MAAMC,QAA8B,GAAG,EAAE;EACzC,KAAK,MAAMC,KAAK,IAAIF,MAAM,EAAE;IAC3B,IAAI;MACH,MAAME,KAAK,CAACC,GAAG,CAAC,MAAMJ,WAAW,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,OAAOK,KAAK,EAAE;MACfH,QAAQ,CAACI,IAAI,CAAC;QACbH,KAAK,EAAEA,KAAK,CAACI,IAAI;QACjBC,MAAM,EAAEH,KAAK,YAAYI,KAAK,GAAGJ,KAAK,CAACK,OAAO,GAAGC,MAAM,CAACN,KAAK;MAC9D,CAAC,CAAC;IACH;EACD;EACA,OAAO;IAAEO,MAAM,EAAEV,QAAQ,CAACW,MAAM,KAAK,CAAC;IAAEZ,MAAM,EAAEA,MAAM,CAACY,MAAM;IAAEX;EAAS,CAAC;AAC1E;;AAEA;AACA,OAAO,SAASY,iBAAiBA,CAACC,MAAyB,EAAEC,OAAO,GAAG,gBAAgB,EAAQ;EAC9F,IAAID,MAAM,CAACH,MAAM,EAAE;EACnB,MAAMK,KAAK,GAAGF,MAAM,CAACb,QAAQ,CAACgB,GAAG,CAACC,OAAO,IAAI,OAAOA,OAAO,CAAChB,KAAK,KAAKgB,OAAO,CAACX,MAAM,EAAE,CAAC;EACvF,MAAM,IAAIC,KAAK,CACd,GAAGO,OAAO,WAAWD,MAAM,CAACb,QAAQ,CAACW,MAAM,OAAOE,MAAM,CAACd,MAAM,aAAagB,KAAK,CAACG,IAAI,CAAC,IAAI,CAAC,EAC7F,CAAC;AACF;;AAEA;AACA,OAAO,SAASC,MAAMA,CAACC,SAAkB,EAAEZ,OAAe,EAAqB;EAC9E,IAAI,CAACY,SAAS,EAAE,MAAM,IAAIb,KAAK,CAACC,OAAO,CAAC;AACzC;AAYA;AACA;AACA;AACA;AACA,OAAO,SAASa,mBAAmBA,CAAA,EAA+C;EACjF,MAAMC,KAAK,GAAG,IAAIC,GAAG,CAAmD,CAAC;EACzE,MAAMC,KAAK,GAAG,IAAIC,GAAG,CAAQ,CAAC;EAC9B,OAAO;IACNC,GAAGA,CAACC,KAAK,EAAEC,KAAK,EAAEC,KAAK,GAAG,CAAC,EAAE;MAC5BP,KAAK,CAACQ,GAAG,CAACH,KAAK,EAAE;QAAEC,KAAK;QAAEG,SAAS,EAAEF;MAAM,CAAC,CAAC;IAC9C,CAAC;IACDG,MAAMA,CAACL,KAAK,EAAE;MACb,IAAIA,KAAK,KAAKM,SAAS,EAAEX,KAAK,CAACY,KAAK,CAAC,CAAC,CAAC,KAClCZ,KAAK,CAACa,MAAM,CAACR,KAAK,CAAC;IACzB,CAAC;IACDS,cAAcA,CAACT,KAAK,EAAE;MACrB,MAAMU,KAAK,GAAGf,KAAK,CAACgB,GAAG,CAACX,KAAK,CAAC;MAC9B,IAAI,CAACU,KAAK,EAAE;MACZA,KAAK,CAACN,SAAS,IAAI,CAAC;MACpB,IAAIM,KAAK,CAACN,SAAS,IAAI,CAAC,EAAET,KAAK,CAACa,MAAM,CAACR,KAAK,CAAC;MAC7CH,KAAK,CAACe,GAAG,CAACZ,KAAK,CAAC;MAChB,MAAMU,KAAK,CAACT,KAAK,CAAC,CAAC;IACpB,CAAC;IACDJ,KAAK,EAAEA,CAAA,KAAM,CAAC,GAAGA,KAAK;EACvB,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Test helpers shared by every package: conformance suites that return plain
5
+ * reports, so they run in Jest and on a device alike. Production code never
6
+ * imports this entrypoint.
7
+ */
8
+ export { REDACTION_PROBES, redactionConformance } from "./redaction.js";
9
+ export { createManualScheduler } from "./scheduler.js";
10
+ export { createFaultRegistry, ensure, expectConformance, runChecks } from "./conformance.js";
11
+ export { createManualLifecycle } from "./lifecycle.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["REDACTION_PROBES","redactionConformance","createManualScheduler","createFaultRegistry","ensure","expectConformance","runChecks","createManualLifecycle"],"sourceRoot":"../../../src","sources":["testing/index.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA,SACCA,gBAAgB,EAChBC,oBAAoB,QAId,gBAAa;AACpB,SAASC,qBAAqB,QAA8B,gBAAa;AACzE,SACCC,mBAAmB,EACnBC,MAAM,EACNC,iBAAiB,EACjBC,SAAS,QAGH,kBAAe;AACtB,SAASC,qBAAqB,QAA8B,gBAAa","ignoreList":[]}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * A lifecycle a test moves by hand (CORE-14). It runs the real port over a scripted
5
+ * `AppState`, so transitions, de-duplication and reference counting behave exactly
6
+ * as they do on a device.
7
+ */
8
+ import { createAppLifecycle } from "../runtime/lifecycle.js";
9
+ export function createManualLifecycle(initial = 'active') {
10
+ let state = initial;
11
+ const handlers = new Set();
12
+ const source = {
13
+ get currentState() {
14
+ return state;
15
+ },
16
+ addEventListener(_type, handler) {
17
+ handlers.add(handler);
18
+ return {
19
+ remove: () => handlers.delete(handler)
20
+ };
21
+ }
22
+ };
23
+ return {
24
+ port: createAppLifecycle(() => source),
25
+ set(next) {
26
+ state = next;
27
+ for (const handler of [...handlers]) handler(next);
28
+ },
29
+ isSubscribed: () => handlers.size > 0
30
+ };
31
+ }
32
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createAppLifecycle","createManualLifecycle","initial","state","handlers","Set","source","currentState","addEventListener","_type","handler","add","remove","delete","port","set","next","isSubscribed","size"],"sourceRoot":"../../../src","sources":["testing/lifecycle.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA,SACCA,kBAAkB,QAIZ,yBAAsB;AAU7B,OAAO,SAASC,qBAAqBA,CAACC,OAA0B,GAAG,QAAQ,EAAmB;EAC7F,IAAIC,KAAwB,GAAGD,OAAO;EACtC,MAAME,QAAQ,GAAG,IAAIC,GAAG,CAAwB,CAAC;EACjD,MAAMC,MAAsB,GAAG;IAC9B,IAAIC,YAAYA,CAAA,EAAG;MAClB,OAAOJ,KAAK;IACb,CAAC;IACDK,gBAAgBA,CAACC,KAAK,EAAEC,OAAO,EAAE;MAChCN,QAAQ,CAACO,GAAG,CAACD,OAAO,CAAC;MACrB,OAAO;QAAEE,MAAM,EAAEA,CAAA,KAAMR,QAAQ,CAACS,MAAM,CAACH,OAAO;MAAE,CAAC;IAClD;EACD,CAAC;EACD,OAAO;IACNI,IAAI,EAAEd,kBAAkB,CAAC,MAAMM,MAAM,CAAC;IACtCS,GAAGA,CAACC,IAAI,EAAE;MACTb,KAAK,GAAGa,IAAI;MACZ,KAAK,MAAMN,OAAO,IAAI,CAAC,GAAGN,QAAQ,CAAC,EAAEM,OAAO,CAACM,IAAI,CAAC;IACnD,CAAC;IACDC,YAAY,EAAEA,CAAA,KAAMb,QAAQ,CAACc,IAAI,GAAG;EACrC,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * One set of secrets every package's redaction must remove (CORE-02).
5
+ *
6
+ * Packages redact with different policies (identifier-only, pattern-based,
7
+ * key-based), but none of them may let one of these through. Each package runs
8
+ * this against every redaction entrypoint it has; the report is plain data, so it
9
+ * runs in Jest and on a device alike.
10
+ */
11
+
12
+ const JWT_PAYLOAD = 'eyJzdWIiOiJ1c2VyLTEyMzQ1Njc4OTAiLCJlbWFpbCI6ImFAYi5jbyJ9';
13
+ const JWT = `eyJhbGciOiJIUzI1NiJ9.${JWT_PAYLOAD}.c2lnbmF0dXJlLXZhbHVl`;
14
+ const URL_TOKEN = 'tok3nV4lue9x';
15
+ const EMAIL = 'jane.doe+chip@example.com';
16
+ const UUID = '3f2b8c1e-9a4d-4e6f-8b2a-1c3d5e7f9a0b';
17
+ const PAYLOAD = 'QmFzZTY0UGF5bG9hZFRoYXRJc0xvbmdFbm91Z2hUb0JlQVNlY3JldEJsb2JYWVo';
18
+ export const REDACTION_PROBES = Object.freeze([{
19
+ name: 'a JWT',
20
+ input: `token rejected: ${JWT}`,
21
+ secret: JWT_PAYLOAD
22
+ }, {
23
+ name: 'a URL carrying a token',
24
+ input: `GET https://api.example.com/v1/chat?access_token=${URL_TOKEN} failed`,
25
+ secret: URL_TOKEN
26
+ }, {
27
+ name: 'an e-mail address',
28
+ input: `no account for ${EMAIL}`,
29
+ secret: EMAIL
30
+ }, {
31
+ name: 'a UUID',
32
+ input: `device ${UUID} refused`,
33
+ secret: UUID
34
+ }, {
35
+ name: 'a base64 payload',
36
+ input: `body=${PAYLOAD}`,
37
+ secret: PAYLOAD
38
+ }, {
39
+ name: 'an Error whose message carries a token',
40
+ input: new Error(`request failed: ${JWT}`),
41
+ secret: JWT_PAYLOAD
42
+ }, {
43
+ name: 'an object carrying a JWT under an innocent key',
44
+ input: {
45
+ reason: `expired ${JWT}`
46
+ },
47
+ secret: JWT_PAYLOAD,
48
+ structured: true
49
+ }, {
50
+ name: 'a nested object carrying an e-mail address',
51
+ input: {
52
+ request: {
53
+ owner: EMAIL
54
+ }
55
+ },
56
+ secret: EMAIL,
57
+ structured: true
58
+ }]);
59
+ /**
60
+ * Everything a log line could show. An Error goes in with its message and its own
61
+ * fields: JSON.stringify renders one as `{}`, which would pass any secret.
62
+ */
63
+ function serialize(value) {
64
+ if (typeof value === 'string') return value;
65
+ try {
66
+ if (value instanceof Error) {
67
+ return `${value.name}: ${value.message} ${JSON.stringify({
68
+ ...value
69
+ })}`;
70
+ }
71
+ // JSON.stringify returns undefined for undefined and functions at run time.
72
+ const json = JSON.stringify(value, (_key, inner) => inner instanceof Error ? `${inner.name}: ${inner.message}` : inner);
73
+ return json ?? String(value);
74
+ } catch {
75
+ return String(value);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Runs every probe through `redact` and reports each secret that survived.
81
+ * `stringsOnly` is for a redactor that only accepts text (rn-auth's `redact`).
82
+ */
83
+ export function redactionConformance(redact, options = {}) {
84
+ const failures = [];
85
+ let checks = 0;
86
+ for (const probe of REDACTION_PROBES) {
87
+ if (options.stringsOnly && typeof probe.input !== 'string') continue;
88
+ if (probe.structured && options.stringsOnly) continue;
89
+ checks += 1;
90
+ let output;
91
+ try {
92
+ output = serialize(redact(probe.input));
93
+ } catch (error) {
94
+ failures.push({
95
+ check: probe.name,
96
+ detail: `redactor threw: ${String(error)}`
97
+ });
98
+ continue;
99
+ }
100
+ if (output.includes(probe.secret)) {
101
+ failures.push({
102
+ check: probe.name,
103
+ detail: 'the secret survived redaction'
104
+ });
105
+ }
106
+ }
107
+ return {
108
+ passed: failures.length === 0,
109
+ checks,
110
+ failures
111
+ };
112
+ }
113
+ //# sourceMappingURL=redaction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["JWT_PAYLOAD","JWT","URL_TOKEN","EMAIL","UUID","PAYLOAD","REDACTION_PROBES","Object","freeze","name","input","secret","Error","reason","structured","request","owner","serialize","value","message","JSON","stringify","json","_key","inner","String","redactionConformance","redact","options","failures","checks","probe","stringsOnly","output","error","push","check","detail","includes","passed","length"],"sourceRoot":"../../../src","sources":["testing/redaction.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * A scheduler a test drives by hand: nothing fires until `advance` moves the
5
+ * clock past it, so timing assertions are exact and instant.
6
+ */
7
+
8
+ export function createManualScheduler(startMs = 0) {
9
+ let clock = startMs;
10
+ let nextId = 1;
11
+ const timers = new Map();
12
+ return {
13
+ setTimeout(callback, ms) {
14
+ const id = nextId++;
15
+ timers.set(id, {
16
+ at: clock + Math.max(0, ms),
17
+ callback
18
+ });
19
+ return id;
20
+ },
21
+ clearTimeout(handle) {
22
+ timers.delete(handle);
23
+ },
24
+ now: () => clock,
25
+ advance(ms) {
26
+ const target = clock + ms;
27
+ for (;;) {
28
+ let dueId;
29
+ let dueAt = Infinity;
30
+ for (const [id, timer] of timers) {
31
+ if (timer.at <= target && timer.at < dueAt) {
32
+ dueId = id;
33
+ dueAt = timer.at;
34
+ }
35
+ }
36
+ if (dueId === undefined) break;
37
+ const timer = timers.get(dueId);
38
+ timers.delete(dueId);
39
+ clock = dueAt;
40
+ timer?.callback();
41
+ }
42
+ clock = target;
43
+ },
44
+ pending: () => timers.size
45
+ };
46
+ }
47
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["createManualScheduler","startMs","clock","nextId","timers","Map","setTimeout","callback","ms","id","set","at","Math","max","clearTimeout","handle","delete","now","advance","target","dueId","dueAt","Infinity","timer","undefined","get","pending","size"],"sourceRoot":"../../../src","sources":["testing/scheduler.ts"],"mappings":";;AAAA;AACA;AACA;AACA;;AAYA,OAAO,SAASA,qBAAqBA,CAACC,OAAO,GAAG,CAAC,EAAmB;EACnE,IAAIC,KAAK,GAAGD,OAAO;EACnB,IAAIE,MAAM,GAAG,CAAC;EACd,MAAMC,MAAM,GAAG,IAAIC,GAAG,CAA+C,CAAC;EAEtE,OAAO;IACNC,UAAUA,CAACC,QAAQ,EAAEC,EAAE,EAAE;MACxB,MAAMC,EAAE,GAAGN,MAAM,EAAE;MACnBC,MAAM,CAACM,GAAG,CAACD,EAAE,EAAE;QAAEE,EAAE,EAAET,KAAK,GAAGU,IAAI,CAACC,GAAG,CAAC,CAAC,EAAEL,EAAE,CAAC;QAAED;MAAS,CAAC,CAAC;MACzD,OAAOE,EAAE;IACV,CAAC;IACDK,YAAYA,CAACC,MAAM,EAAE;MACpBX,MAAM,CAACY,MAAM,CAACD,MAAgB,CAAC;IAChC,CAAC;IACDE,GAAG,EAAEA,CAAA,KAAMf,KAAK;IAChBgB,OAAOA,CAACV,EAAE,EAAE;MACX,MAAMW,MAAM,GAAGjB,KAAK,GAAGM,EAAE;MACzB,SAAS;QACR,IAAIY,KAAyB;QAC7B,IAAIC,KAAK,GAAGC,QAAQ;QACpB,KAAK,MAAM,CAACb,EAAE,EAAEc,KAAK,CAAC,IAAInB,MAAM,EAAE;UACjC,IAAImB,KAAK,CAACZ,EAAE,IAAIQ,MAAM,IAAII,KAAK,CAACZ,EAAE,GAAGU,KAAK,EAAE;YAC3CD,KAAK,GAAGX,EAAE;YACVY,KAAK,GAAGE,KAAK,CAACZ,EAAE;UACjB;QACD;QACA,IAAIS,KAAK,KAAKI,SAAS,EAAE;QACzB,MAAMD,KAAK,GAAGnB,MAAM,CAACqB,GAAG,CAACL,KAAK,CAAC;QAC/BhB,MAAM,CAACY,MAAM,CAACI,KAAK,CAAC;QACpBlB,KAAK,GAAGmB,KAAK;QACbE,KAAK,EAAEhB,QAAQ,CAAC,CAAC;MAClB;MACAL,KAAK,GAAGiB,MAAM;IACf,CAAC;IACDO,OAAO,EAAEA,CAAA,KAAMtB,MAAM,CAACuB;EACvB,CAAC;AACF","ignoreList":[]}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * One diagnostic stream for every package (CORE-08).
3
+ *
4
+ * Each package keeps its own typed events (`AdEvent`, `PaymentEvent`...), and also
5
+ * reports what it observed as an `SdkDiagnostic` through a channel. An app installs
6
+ * one `DiagnosticSink` and receives every package's diagnostics in one shape, so
7
+ * wiring crash reporting or analytics is one adapter rather than ten.
8
+ *
9
+ * Sinks live in a registry anchored on `Symbol.for`, so a sink installed through
10
+ * one copy of rn-core also receives diagnostics from packages bundling another.
11
+ * Every context passes through a redactor before any sink sees it.
12
+ */
13
+ import type { Unsubscribe } from '../listeners';
14
+ import { type Redactor } from '../redact';
15
+ export type DiagnosticSeverity = 'debug' | 'info' | 'warn' | 'error';
16
+ export interface SdkDiagnostic<Code extends string = string> {
17
+ /** The package that reported it, e.g. `rn-payment`. */
18
+ readonly pkg: string;
19
+ /** That package's stable diagnostic or event code. */
20
+ readonly code: Code;
21
+ readonly severity: DiagnosticSeverity;
22
+ /** Epoch milliseconds. */
23
+ readonly at: number;
24
+ /** Ties together everything reported within one operation, when the package has one. */
25
+ readonly correlationId?: string;
26
+ /** Already redacted. */
27
+ readonly context?: Readonly<Record<string, unknown>>;
28
+ }
29
+ export type DiagnosticSink = (diagnostic: SdkDiagnostic) => void;
30
+ /**
31
+ * Sends every package's diagnostics to `sink` until the returned function is
32
+ * called. A sink that throws is reported on a fresh task and never affects the
33
+ * package that emitted.
34
+ */
35
+ export declare function installSdkSink(sink: DiagnosticSink): Unsubscribe;
36
+ /** Whether any sink is installed, for a package that would do extra work only to feed one. */
37
+ export declare function hasSdkSinks(): boolean;
38
+ export interface DiagnosticChannelOptions {
39
+ /** A package-level sink, in addition to every installed one. */
40
+ readonly sink?: DiagnosticSink | undefined;
41
+ /** Defaults to rn-core's identifier-only redactor. */
42
+ readonly redactor?: Redactor | undefined;
43
+ readonly now?: (() => number) | undefined;
44
+ }
45
+ export interface DiagnosticChannel<Code extends string> {
46
+ emit(code: Code, severity: DiagnosticSeverity, context?: Readonly<Record<string, unknown>>, correlationId?: string): void;
47
+ }
48
+ export declare function createDiagnosticChannel<Code extends string = string>(pkg: string, options?: DiagnosticChannelOptions): DiagnosticChannel<Code>;
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/diagnostics/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1D,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAErE,MAAM,WAAW,aAAa,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM;IAC1D,uDAAuD;IACvD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,0BAA0B;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,wFAAwF;IACxF,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,wBAAwB;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACrD;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,aAAa,KAAK,IAAI,CAAC;AAUjE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,cAAc,GAAG,WAAW,CAShE;AAED,8FAA8F;AAC9F,wBAAgB,WAAW,IAAI,OAAO,CAErC;AAED,MAAM,WAAW,wBAAwB;IACxC,gEAAgE;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAC3C,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,CAAC;CAC1C;AAED,MAAM,WAAW,iBAAiB,CAAC,IAAI,SAAS,MAAM;IACrD,IAAI,CACH,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC3C,aAAa,CAAC,EAAE,MAAM,GACpB,IAAI,CAAC;CACR;AAED,wBAAgB,uBAAuB,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,EACnE,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,wBAA6B,GACpC,iBAAiB,CAAC,IAAI,CAAC,CA0BzB"}