@fixprompt/react-native 0.0.1
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/README.md +119 -0
- package/dist/__mocks__/async-storage.d.ts +9 -0
- package/dist/__mocks__/react-native.d.ts +11 -0
- package/dist/buffer.d.ts +23 -0
- package/dist/console.d.ts +12 -0
- package/dist/device.d.ts +7 -0
- package/dist/handlers.d.ts +7 -0
- package/dist/index.cjs +825 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +791 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +10 -0
- package/dist/init.spec.d.ts +1 -0
- package/dist/session.d.ts +12 -0
- package/dist/state.d.ts +23 -0
- package/dist/transport.d.ts +13 -0
- package/dist/types.d.ts +54 -0
- package/dist/version.d.ts +2 -0
- package/package.json +54 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// node_modules/promise/setimmediate/core.js
|
|
34
|
+
var require_core = __commonJS({
|
|
35
|
+
"node_modules/promise/setimmediate/core.js"(exports2, module2) {
|
|
36
|
+
"use strict";
|
|
37
|
+
function noop() {
|
|
38
|
+
}
|
|
39
|
+
var LAST_ERROR = null;
|
|
40
|
+
var IS_ERROR = {};
|
|
41
|
+
function getThen(obj) {
|
|
42
|
+
try {
|
|
43
|
+
return obj.then;
|
|
44
|
+
} catch (ex) {
|
|
45
|
+
LAST_ERROR = ex;
|
|
46
|
+
return IS_ERROR;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function tryCallOne(fn, a) {
|
|
50
|
+
try {
|
|
51
|
+
return fn(a);
|
|
52
|
+
} catch (ex) {
|
|
53
|
+
LAST_ERROR = ex;
|
|
54
|
+
return IS_ERROR;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function tryCallTwo(fn, a, b) {
|
|
58
|
+
try {
|
|
59
|
+
fn(a, b);
|
|
60
|
+
} catch (ex) {
|
|
61
|
+
LAST_ERROR = ex;
|
|
62
|
+
return IS_ERROR;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
module2.exports = Promise2;
|
|
66
|
+
function Promise2(fn) {
|
|
67
|
+
if (typeof this !== "object") {
|
|
68
|
+
throw new TypeError("Promises must be constructed via new");
|
|
69
|
+
}
|
|
70
|
+
if (typeof fn !== "function") {
|
|
71
|
+
throw new TypeError("Promise constructor's argument is not a function");
|
|
72
|
+
}
|
|
73
|
+
this._x = 0;
|
|
74
|
+
this._y = 0;
|
|
75
|
+
this._z = null;
|
|
76
|
+
this._A = null;
|
|
77
|
+
if (fn === noop) return;
|
|
78
|
+
doResolve(fn, this);
|
|
79
|
+
}
|
|
80
|
+
Promise2._B = null;
|
|
81
|
+
Promise2._C = null;
|
|
82
|
+
Promise2._D = noop;
|
|
83
|
+
Promise2.prototype.then = function(onFulfilled, onRejected) {
|
|
84
|
+
if (this.constructor !== Promise2) {
|
|
85
|
+
return safeThen(this, onFulfilled, onRejected);
|
|
86
|
+
}
|
|
87
|
+
var res = new Promise2(noop);
|
|
88
|
+
handle(this, new Handler(onFulfilled, onRejected, res));
|
|
89
|
+
return res;
|
|
90
|
+
};
|
|
91
|
+
function safeThen(self, onFulfilled, onRejected) {
|
|
92
|
+
return new self.constructor(function(resolve2, reject2) {
|
|
93
|
+
var res = new Promise2(noop);
|
|
94
|
+
res.then(resolve2, reject2);
|
|
95
|
+
handle(self, new Handler(onFulfilled, onRejected, res));
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function handle(self, deferred) {
|
|
99
|
+
while (self._y === 3) {
|
|
100
|
+
self = self._z;
|
|
101
|
+
}
|
|
102
|
+
if (Promise2._B) {
|
|
103
|
+
Promise2._B(self);
|
|
104
|
+
}
|
|
105
|
+
if (self._y === 0) {
|
|
106
|
+
if (self._x === 0) {
|
|
107
|
+
self._x = 1;
|
|
108
|
+
self._A = deferred;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (self._x === 1) {
|
|
112
|
+
self._x = 2;
|
|
113
|
+
self._A = [self._A, deferred];
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
self._A.push(deferred);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
handleResolved(self, deferred);
|
|
120
|
+
}
|
|
121
|
+
function handleResolved(self, deferred) {
|
|
122
|
+
setImmediate(function() {
|
|
123
|
+
var cb = self._y === 1 ? deferred.onFulfilled : deferred.onRejected;
|
|
124
|
+
if (cb === null) {
|
|
125
|
+
if (self._y === 1) {
|
|
126
|
+
resolve(deferred.promise, self._z);
|
|
127
|
+
} else {
|
|
128
|
+
reject(deferred.promise, self._z);
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
var ret = tryCallOne(cb, self._z);
|
|
133
|
+
if (ret === IS_ERROR) {
|
|
134
|
+
reject(deferred.promise, LAST_ERROR);
|
|
135
|
+
} else {
|
|
136
|
+
resolve(deferred.promise, ret);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function resolve(self, newValue) {
|
|
141
|
+
if (newValue === self) {
|
|
142
|
+
return reject(
|
|
143
|
+
self,
|
|
144
|
+
new TypeError("A promise cannot be resolved with itself.")
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
if (newValue && (typeof newValue === "object" || typeof newValue === "function")) {
|
|
148
|
+
var then = getThen(newValue);
|
|
149
|
+
if (then === IS_ERROR) {
|
|
150
|
+
return reject(self, LAST_ERROR);
|
|
151
|
+
}
|
|
152
|
+
if (then === self.then && newValue instanceof Promise2) {
|
|
153
|
+
self._y = 3;
|
|
154
|
+
self._z = newValue;
|
|
155
|
+
finale(self);
|
|
156
|
+
return;
|
|
157
|
+
} else if (typeof then === "function") {
|
|
158
|
+
doResolve(then.bind(newValue), self);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
self._y = 1;
|
|
163
|
+
self._z = newValue;
|
|
164
|
+
finale(self);
|
|
165
|
+
}
|
|
166
|
+
function reject(self, newValue) {
|
|
167
|
+
self._y = 2;
|
|
168
|
+
self._z = newValue;
|
|
169
|
+
if (Promise2._C) {
|
|
170
|
+
Promise2._C(self, newValue);
|
|
171
|
+
}
|
|
172
|
+
finale(self);
|
|
173
|
+
}
|
|
174
|
+
function finale(self) {
|
|
175
|
+
if (self._x === 1) {
|
|
176
|
+
handle(self, self._A);
|
|
177
|
+
self._A = null;
|
|
178
|
+
}
|
|
179
|
+
if (self._x === 2) {
|
|
180
|
+
for (var i = 0; i < self._A.length; i++) {
|
|
181
|
+
handle(self, self._A[i]);
|
|
182
|
+
}
|
|
183
|
+
self._A = null;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
function Handler(onFulfilled, onRejected, promise) {
|
|
187
|
+
this.onFulfilled = typeof onFulfilled === "function" ? onFulfilled : null;
|
|
188
|
+
this.onRejected = typeof onRejected === "function" ? onRejected : null;
|
|
189
|
+
this.promise = promise;
|
|
190
|
+
}
|
|
191
|
+
function doResolve(fn, promise) {
|
|
192
|
+
var done = false;
|
|
193
|
+
var res = tryCallTwo(fn, function(value) {
|
|
194
|
+
if (done) return;
|
|
195
|
+
done = true;
|
|
196
|
+
resolve(promise, value);
|
|
197
|
+
}, function(reason) {
|
|
198
|
+
if (done) return;
|
|
199
|
+
done = true;
|
|
200
|
+
reject(promise, reason);
|
|
201
|
+
});
|
|
202
|
+
if (!done && res === IS_ERROR) {
|
|
203
|
+
done = true;
|
|
204
|
+
reject(promise, LAST_ERROR);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// node_modules/promise/setimmediate/rejection-tracking.js
|
|
211
|
+
var require_rejection_tracking = __commonJS({
|
|
212
|
+
"node_modules/promise/setimmediate/rejection-tracking.js"(exports2) {
|
|
213
|
+
"use strict";
|
|
214
|
+
var Promise2 = require_core();
|
|
215
|
+
var DEFAULT_WHITELIST = [
|
|
216
|
+
ReferenceError,
|
|
217
|
+
TypeError,
|
|
218
|
+
RangeError
|
|
219
|
+
];
|
|
220
|
+
var enabled = false;
|
|
221
|
+
exports2.disable = disable;
|
|
222
|
+
function disable() {
|
|
223
|
+
enabled = false;
|
|
224
|
+
Promise2._B = null;
|
|
225
|
+
Promise2._C = null;
|
|
226
|
+
}
|
|
227
|
+
exports2.enable = enable;
|
|
228
|
+
function enable(options) {
|
|
229
|
+
options = options || {};
|
|
230
|
+
if (enabled) disable();
|
|
231
|
+
enabled = true;
|
|
232
|
+
var id = 0;
|
|
233
|
+
var displayId = 0;
|
|
234
|
+
var rejections = {};
|
|
235
|
+
Promise2._B = function(promise) {
|
|
236
|
+
if (promise._y === 2 && // IS REJECTED
|
|
237
|
+
rejections[promise._E]) {
|
|
238
|
+
if (rejections[promise._E].logged) {
|
|
239
|
+
onHandled(promise._E);
|
|
240
|
+
} else {
|
|
241
|
+
clearTimeout(rejections[promise._E].timeout);
|
|
242
|
+
}
|
|
243
|
+
delete rejections[promise._E];
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
Promise2._C = function(promise, err) {
|
|
247
|
+
if (promise._x === 0) {
|
|
248
|
+
promise._E = id++;
|
|
249
|
+
rejections[promise._E] = {
|
|
250
|
+
displayId: null,
|
|
251
|
+
error: err,
|
|
252
|
+
timeout: setTimeout(
|
|
253
|
+
onUnhandled.bind(null, promise._E),
|
|
254
|
+
// For reference errors and type errors, this almost always
|
|
255
|
+
// means the programmer made a mistake, so log them after just
|
|
256
|
+
// 100ms
|
|
257
|
+
// otherwise, wait 2 seconds to see if they get handled
|
|
258
|
+
matchWhitelist(err, DEFAULT_WHITELIST) ? 100 : 2e3
|
|
259
|
+
),
|
|
260
|
+
logged: false
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
function onUnhandled(id2) {
|
|
265
|
+
if (options.allRejections || matchWhitelist(
|
|
266
|
+
rejections[id2].error,
|
|
267
|
+
options.whitelist || DEFAULT_WHITELIST
|
|
268
|
+
)) {
|
|
269
|
+
rejections[id2].displayId = displayId++;
|
|
270
|
+
if (options.onUnhandled) {
|
|
271
|
+
rejections[id2].logged = true;
|
|
272
|
+
options.onUnhandled(
|
|
273
|
+
rejections[id2].displayId,
|
|
274
|
+
rejections[id2].error
|
|
275
|
+
);
|
|
276
|
+
} else {
|
|
277
|
+
rejections[id2].logged = true;
|
|
278
|
+
logError(
|
|
279
|
+
rejections[id2].displayId,
|
|
280
|
+
rejections[id2].error
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
function onHandled(id2) {
|
|
286
|
+
if (rejections[id2].logged) {
|
|
287
|
+
if (options.onHandled) {
|
|
288
|
+
options.onHandled(rejections[id2].displayId, rejections[id2].error);
|
|
289
|
+
} else if (!rejections[id2].onUnhandled) {
|
|
290
|
+
console.warn(
|
|
291
|
+
"Promise Rejection Handled (id: " + rejections[id2].displayId + "):"
|
|
292
|
+
);
|
|
293
|
+
console.warn(
|
|
294
|
+
' This means you can ignore any previous messages of the form "Possible Unhandled Promise Rejection" with id ' + rejections[id2].displayId + "."
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
function logError(id, error) {
|
|
301
|
+
console.warn("Possible Unhandled Promise Rejection (id: " + id + "):");
|
|
302
|
+
var errStr = (error && (error.stack || error)) + "";
|
|
303
|
+
errStr.split("\n").forEach(function(line) {
|
|
304
|
+
console.warn(" " + line);
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
function matchWhitelist(error, list) {
|
|
308
|
+
return list.some(function(cls) {
|
|
309
|
+
return error instanceof cls;
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// src/index.ts
|
|
316
|
+
var src_exports = {};
|
|
317
|
+
__export(src_exports, {
|
|
318
|
+
SDK_NAME: () => SDK_NAME,
|
|
319
|
+
SDK_VERSION: () => SDK_VERSION,
|
|
320
|
+
_resetForTests: () => _resetForTests,
|
|
321
|
+
captureException: () => captureException,
|
|
322
|
+
initFixPrompt: () => initFixPrompt,
|
|
323
|
+
setUser: () => setUser
|
|
324
|
+
});
|
|
325
|
+
module.exports = __toCommonJS(src_exports);
|
|
326
|
+
|
|
327
|
+
// src/state.ts
|
|
328
|
+
var STATE_KEY = "__fixprompt_rn_state__";
|
|
329
|
+
function globalScope() {
|
|
330
|
+
if (typeof globalThis !== "undefined") return globalThis;
|
|
331
|
+
return {};
|
|
332
|
+
}
|
|
333
|
+
function getState() {
|
|
334
|
+
const g = globalScope();
|
|
335
|
+
if (!g[STATE_KEY]) {
|
|
336
|
+
g[STATE_KEY] = {
|
|
337
|
+
initialized: false,
|
|
338
|
+
config: null,
|
|
339
|
+
sessionId: null,
|
|
340
|
+
deviceId: null,
|
|
341
|
+
user: null,
|
|
342
|
+
cleanup: {}
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
return g[STATE_KEY];
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// src/session.ts
|
|
349
|
+
var import_async_storage = __toESM(require("@react-native-async-storage/async-storage"));
|
|
350
|
+
var DEVICE_KEY = "@fixprompt/device_id";
|
|
351
|
+
function uuid() {
|
|
352
|
+
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
353
|
+
return globalThis.crypto.randomUUID();
|
|
354
|
+
}
|
|
355
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
356
|
+
const r = Math.random() * 16 | 0;
|
|
357
|
+
const v = c === "x" ? r : r & 3 | 8;
|
|
358
|
+
return v.toString(16);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function newSessionId() {
|
|
362
|
+
return uuid();
|
|
363
|
+
}
|
|
364
|
+
async function getDeviceId() {
|
|
365
|
+
try {
|
|
366
|
+
const SecureStore = await tryImport("expo-secure-store");
|
|
367
|
+
if (SecureStore) {
|
|
368
|
+
const existing = await SecureStore.getItemAsync("fixprompt_device_id");
|
|
369
|
+
if (existing) return existing;
|
|
370
|
+
const fresh = uuid();
|
|
371
|
+
await SecureStore.setItemAsync("fixprompt_device_id", fresh);
|
|
372
|
+
return fresh;
|
|
373
|
+
}
|
|
374
|
+
} catch {
|
|
375
|
+
}
|
|
376
|
+
try {
|
|
377
|
+
const existing = await import_async_storage.default.getItem(DEVICE_KEY);
|
|
378
|
+
if (existing) return existing;
|
|
379
|
+
const fresh = uuid();
|
|
380
|
+
await import_async_storage.default.setItem(DEVICE_KEY, fresh);
|
|
381
|
+
return fresh;
|
|
382
|
+
} catch {
|
|
383
|
+
return uuid();
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
async function tryImport(spec) {
|
|
387
|
+
try {
|
|
388
|
+
return require(spec);
|
|
389
|
+
} catch {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/buffer.ts
|
|
395
|
+
var import_async_storage2 = __toESM(require("@react-native-async-storage/async-storage"));
|
|
396
|
+
var STORAGE_KEY = "@fixprompt/buffer";
|
|
397
|
+
var MAX_BUFFER = 200;
|
|
398
|
+
var MAX_AGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
399
|
+
var OfflineBuffer = class {
|
|
400
|
+
constructor() {
|
|
401
|
+
this.items = [];
|
|
402
|
+
this.loaded = false;
|
|
403
|
+
this.persistTimer = null;
|
|
404
|
+
}
|
|
405
|
+
/** Load the persisted buffer once, on first use. */
|
|
406
|
+
async load() {
|
|
407
|
+
if (this.loaded) return;
|
|
408
|
+
this.loaded = true;
|
|
409
|
+
try {
|
|
410
|
+
const raw = await import_async_storage2.default.getItem(STORAGE_KEY);
|
|
411
|
+
if (!raw) return;
|
|
412
|
+
const parsed = JSON.parse(raw);
|
|
413
|
+
const cutoff = Date.now() - MAX_AGE_MS;
|
|
414
|
+
this.items = parsed.filter((e) => e?.ts > cutoff).slice(-MAX_BUFFER);
|
|
415
|
+
} catch {
|
|
416
|
+
this.items = [];
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
push(payload) {
|
|
420
|
+
this.items.push({ ts: Date.now(), payload });
|
|
421
|
+
if (this.items.length > MAX_BUFFER) this.items.shift();
|
|
422
|
+
this.schedulePersist();
|
|
423
|
+
}
|
|
424
|
+
async drain() {
|
|
425
|
+
if (!this.loaded) await this.load();
|
|
426
|
+
const out = this.items.map((e) => e.payload);
|
|
427
|
+
this.items = [];
|
|
428
|
+
this.schedulePersist();
|
|
429
|
+
return out;
|
|
430
|
+
}
|
|
431
|
+
size() {
|
|
432
|
+
return this.items.length;
|
|
433
|
+
}
|
|
434
|
+
schedulePersist() {
|
|
435
|
+
if (this.persistTimer) return;
|
|
436
|
+
this.persistTimer = setTimeout(async () => {
|
|
437
|
+
this.persistTimer = null;
|
|
438
|
+
try {
|
|
439
|
+
await import_async_storage2.default.setItem(STORAGE_KEY, JSON.stringify(this.items));
|
|
440
|
+
} catch {
|
|
441
|
+
}
|
|
442
|
+
}, 500);
|
|
443
|
+
}
|
|
444
|
+
/** Tests only. */
|
|
445
|
+
_resetForTests() {
|
|
446
|
+
this.items = [];
|
|
447
|
+
this.loaded = false;
|
|
448
|
+
if (this.persistTimer) {
|
|
449
|
+
clearTimeout(this.persistTimer);
|
|
450
|
+
this.persistTimer = null;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
var offlineBuffer = new OfflineBuffer();
|
|
455
|
+
|
|
456
|
+
// src/device.ts
|
|
457
|
+
var import_react_native = require("react-native");
|
|
458
|
+
function getDeviceAttrs() {
|
|
459
|
+
return {
|
|
460
|
+
platform: String(import_react_native.Platform.OS),
|
|
461
|
+
os_version: String(import_react_native.Platform.Version ?? "unknown"),
|
|
462
|
+
rn_version: import_react_native.Platform.constants?.reactNativeVersion ? Object.values(import_react_native.Platform.constants.reactNativeVersion).join(".") : void 0
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// src/version.ts
|
|
467
|
+
var SDK_NAME = "@fixprompt/react-native";
|
|
468
|
+
var SDK_VERSION = "0.0.1";
|
|
469
|
+
|
|
470
|
+
// src/transport.ts
|
|
471
|
+
var REQUEST_TIMEOUT_MS = 8e3;
|
|
472
|
+
function sendEvent(config, payload) {
|
|
473
|
+
const state = getState();
|
|
474
|
+
const event = {
|
|
475
|
+
service: payload.service ?? config.service,
|
|
476
|
+
app: payload.app ?? config.app,
|
|
477
|
+
env: payload.env ?? config.env,
|
|
478
|
+
level: payload.level,
|
|
479
|
+
message: payload.message,
|
|
480
|
+
stack: payload.stack,
|
|
481
|
+
attrs: {
|
|
482
|
+
...payload.attrs ?? {},
|
|
483
|
+
...getDeviceAttrs(),
|
|
484
|
+
sdk: SDK_NAME,
|
|
485
|
+
sdk_version: SDK_VERSION,
|
|
486
|
+
release: config.release,
|
|
487
|
+
session_id: state.sessionId,
|
|
488
|
+
device_id: state.deviceId,
|
|
489
|
+
user_id: state.user?.id,
|
|
490
|
+
user_email: state.user?.email
|
|
491
|
+
},
|
|
492
|
+
synthetic: payload.synthetic
|
|
493
|
+
};
|
|
494
|
+
for (const k of Object.keys(event.attrs)) {
|
|
495
|
+
if (event.attrs[k] === void 0 || event.attrs[k] === null) {
|
|
496
|
+
delete event.attrs[k];
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
void postOrBuffer(config, event);
|
|
500
|
+
}
|
|
501
|
+
async function postOrBuffer(config, event) {
|
|
502
|
+
if (!await tryPost(
|
|
503
|
+
config,
|
|
504
|
+
event,
|
|
505
|
+
/* throwOnFail */
|
|
506
|
+
true
|
|
507
|
+
)) {
|
|
508
|
+
offlineBuffer.push(event);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
if (offlineBuffer.size() === 0) return;
|
|
512
|
+
const queued = await offlineBuffer.drain();
|
|
513
|
+
for (const buffered of queued) {
|
|
514
|
+
if (!await tryPost(config, buffered, true)) {
|
|
515
|
+
offlineBuffer.push(buffered);
|
|
516
|
+
for (let i = queued.indexOf(buffered) + 1; i < queued.length; i++) {
|
|
517
|
+
offlineBuffer.push(queued[i]);
|
|
518
|
+
}
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
async function tryPost(config, event, throwOnFail) {
|
|
524
|
+
try {
|
|
525
|
+
const ctrl = new AbortController();
|
|
526
|
+
const timer = setTimeout(() => ctrl.abort(), REQUEST_TIMEOUT_MS);
|
|
527
|
+
try {
|
|
528
|
+
const res = await fetch(`${config.endpoint.replace(/\/$/, "")}/ingest/log`, {
|
|
529
|
+
method: "POST",
|
|
530
|
+
headers: {
|
|
531
|
+
"Content-Type": "application/json",
|
|
532
|
+
"x-loghub-source": config.source,
|
|
533
|
+
"x-loghub-key": config.projectKey
|
|
534
|
+
},
|
|
535
|
+
body: JSON.stringify(event),
|
|
536
|
+
signal: ctrl.signal
|
|
537
|
+
});
|
|
538
|
+
if (res.status >= 400 && res.status < 500) {
|
|
539
|
+
if (config.debug) {
|
|
540
|
+
console.warn(`[fixprompt] ${res.status} from broker \u2014 dropping event`);
|
|
541
|
+
}
|
|
542
|
+
return true;
|
|
543
|
+
}
|
|
544
|
+
return res.ok;
|
|
545
|
+
} finally {
|
|
546
|
+
clearTimeout(timer);
|
|
547
|
+
}
|
|
548
|
+
} catch (err) {
|
|
549
|
+
if (config.debug) {
|
|
550
|
+
console.warn(`[fixprompt] transport error: ${err.message}`);
|
|
551
|
+
}
|
|
552
|
+
return false;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// src/handlers.ts
|
|
557
|
+
function topStackFrame(stack) {
|
|
558
|
+
if (!stack) return "";
|
|
559
|
+
for (const raw of stack.split("\n")) {
|
|
560
|
+
const line = raw.trim();
|
|
561
|
+
if (!line) continue;
|
|
562
|
+
if (line.startsWith("Error")) continue;
|
|
563
|
+
if (/node_modules|@fixprompt/.test(line)) continue;
|
|
564
|
+
return line.slice(0, 200);
|
|
565
|
+
}
|
|
566
|
+
return stack.split("\n")[0]?.slice(0, 200) ?? "";
|
|
567
|
+
}
|
|
568
|
+
function installGlobalErrorHandler(config) {
|
|
569
|
+
const ErrorUtils = globalThis.ErrorUtils;
|
|
570
|
+
if (!ErrorUtils?.setGlobalHandler) {
|
|
571
|
+
return () => void 0;
|
|
572
|
+
}
|
|
573
|
+
const previous = ErrorUtils.getGlobalHandler?.();
|
|
574
|
+
const handler = (error, isFatal) => {
|
|
575
|
+
try {
|
|
576
|
+
sendEvent(config, {
|
|
577
|
+
level: isFatal ? "error" : "warn",
|
|
578
|
+
message: error?.message ?? "Uncaught error",
|
|
579
|
+
stack: typeof error?.stack === "string" ? error.stack : void 0,
|
|
580
|
+
attrs: {
|
|
581
|
+
kind: "rn.globalError",
|
|
582
|
+
severity: isFatal ? "critical" : "error",
|
|
583
|
+
error_name: error?.name,
|
|
584
|
+
top_frame: topStackFrame(error?.stack),
|
|
585
|
+
fatal: !!isFatal
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
} catch {
|
|
589
|
+
}
|
|
590
|
+
previous?.(error, isFatal);
|
|
591
|
+
};
|
|
592
|
+
ErrorUtils.setGlobalHandler(handler);
|
|
593
|
+
return () => {
|
|
594
|
+
if (previous) ErrorUtils.setGlobalHandler(previous);
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
function installRejectionHandler(config) {
|
|
598
|
+
let tracking;
|
|
599
|
+
try {
|
|
600
|
+
tracking = require_rejection_tracking();
|
|
601
|
+
} catch {
|
|
602
|
+
return () => void 0;
|
|
603
|
+
}
|
|
604
|
+
tracking.enable({
|
|
605
|
+
allRejections: true,
|
|
606
|
+
onUnhandled: (id, error) => {
|
|
607
|
+
try {
|
|
608
|
+
const isErr = error instanceof Error;
|
|
609
|
+
sendEvent(config, {
|
|
610
|
+
level: "error",
|
|
611
|
+
message: isErr ? error.message : safeJson(error),
|
|
612
|
+
stack: isErr && typeof error.stack === "string" ? error.stack : void 0,
|
|
613
|
+
attrs: {
|
|
614
|
+
kind: "rn.unhandledrejection",
|
|
615
|
+
severity: "error",
|
|
616
|
+
error_name: isErr ? error.name : typeof error,
|
|
617
|
+
top_frame: isErr ? topStackFrame(error.stack) : ""
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
} catch {
|
|
621
|
+
}
|
|
622
|
+
},
|
|
623
|
+
onHandled: () => void 0
|
|
624
|
+
});
|
|
625
|
+
return () => {
|
|
626
|
+
try {
|
|
627
|
+
tracking.disable();
|
|
628
|
+
} catch {
|
|
629
|
+
}
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
function safeJson(v) {
|
|
633
|
+
try {
|
|
634
|
+
return JSON.stringify(v);
|
|
635
|
+
} catch {
|
|
636
|
+
return String(v);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// src/console.ts
|
|
641
|
+
function shouldCapture(args, patterns) {
|
|
642
|
+
if (patterns.length === 0) return true;
|
|
643
|
+
const first = typeof args[0] === "string" ? args[0] : "";
|
|
644
|
+
return patterns.some((re) => re.test(first));
|
|
645
|
+
}
|
|
646
|
+
function stringify(args) {
|
|
647
|
+
const errArg = args.find((a) => a instanceof Error);
|
|
648
|
+
const message = args.map((a) => {
|
|
649
|
+
if (a instanceof Error) return a.message;
|
|
650
|
+
if (typeof a === "string") return a;
|
|
651
|
+
try {
|
|
652
|
+
return JSON.stringify(a);
|
|
653
|
+
} catch {
|
|
654
|
+
return String(a);
|
|
655
|
+
}
|
|
656
|
+
}).join(" ").slice(0, 4e3);
|
|
657
|
+
return {
|
|
658
|
+
message,
|
|
659
|
+
stack: errArg && typeof errArg.stack === "string" ? errArg.stack : void 0
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
function patchConsoleError(config) {
|
|
663
|
+
const original = console.error.bind(console);
|
|
664
|
+
console.error = (...args) => {
|
|
665
|
+
try {
|
|
666
|
+
if (shouldCapture(args, config.captureTags)) {
|
|
667
|
+
const { message, stack } = stringify(args);
|
|
668
|
+
sendEvent(config, {
|
|
669
|
+
level: "warn",
|
|
670
|
+
message,
|
|
671
|
+
stack,
|
|
672
|
+
attrs: {
|
|
673
|
+
kind: "console.error",
|
|
674
|
+
severity: "warning"
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
} catch {
|
|
679
|
+
}
|
|
680
|
+
return original(...args);
|
|
681
|
+
};
|
|
682
|
+
return () => {
|
|
683
|
+
console.error = original;
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
function patchConsoleWarn(config) {
|
|
687
|
+
const original = console.warn.bind(console);
|
|
688
|
+
console.warn = (...args) => {
|
|
689
|
+
try {
|
|
690
|
+
if (shouldCapture(args, config.captureTags)) {
|
|
691
|
+
const { message, stack } = stringify(args);
|
|
692
|
+
sendEvent(config, {
|
|
693
|
+
level: "warn",
|
|
694
|
+
message,
|
|
695
|
+
stack,
|
|
696
|
+
attrs: {
|
|
697
|
+
kind: "console.warn",
|
|
698
|
+
severity: "warning"
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
} catch {
|
|
703
|
+
}
|
|
704
|
+
return original(...args);
|
|
705
|
+
};
|
|
706
|
+
return () => {
|
|
707
|
+
console.warn = original;
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// src/init.ts
|
|
712
|
+
var DEFAULT_ENDPOINT = "https://geosloghub-production.up.railway.app";
|
|
713
|
+
function resolveConfig(opts) {
|
|
714
|
+
if (!opts?.projectKey) throw new Error("initFixPrompt: projectKey is required");
|
|
715
|
+
if (!opts?.source) throw new Error("initFixPrompt: source is required");
|
|
716
|
+
if (!opts?.service) throw new Error("initFixPrompt: service is required");
|
|
717
|
+
if (!opts?.app) throw new Error("initFixPrompt: app is required");
|
|
718
|
+
return {
|
|
719
|
+
projectKey: opts.projectKey,
|
|
720
|
+
source: opts.source,
|
|
721
|
+
endpoint: (opts.endpoint ?? DEFAULT_ENDPOINT).replace(/\/$/, ""),
|
|
722
|
+
service: opts.service,
|
|
723
|
+
app: opts.app,
|
|
724
|
+
env: opts.env ?? "prod",
|
|
725
|
+
release: opts.release ?? null,
|
|
726
|
+
captureTags: opts.captureTags ?? [],
|
|
727
|
+
patchConsoleWarn: opts.patchConsoleWarn ?? false,
|
|
728
|
+
patchConsoleError: opts.patchConsoleError ?? true,
|
|
729
|
+
debug: opts.debug ?? false
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
function initFixPrompt(opts) {
|
|
733
|
+
const state = getState();
|
|
734
|
+
if (state.initialized) {
|
|
735
|
+
if (opts?.debug) {
|
|
736
|
+
console.warn("[fixprompt] already initialized \u2014 call ignored");
|
|
737
|
+
}
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
const config = resolveConfig(opts);
|
|
741
|
+
state.config = config;
|
|
742
|
+
state.sessionId = newSessionId();
|
|
743
|
+
state.cleanup.removeErrorHandler = installGlobalErrorHandler(config);
|
|
744
|
+
state.cleanup.removeRejectionHandler = installRejectionHandler(config);
|
|
745
|
+
if (config.patchConsoleError) {
|
|
746
|
+
state.cleanup.restoreConsoleError = patchConsoleError(config);
|
|
747
|
+
}
|
|
748
|
+
if (config.patchConsoleWarn) {
|
|
749
|
+
state.cleanup.restoreConsoleWarn = patchConsoleWarn(config);
|
|
750
|
+
}
|
|
751
|
+
state.initialized = true;
|
|
752
|
+
void (async () => {
|
|
753
|
+
try {
|
|
754
|
+
state.deviceId = await getDeviceId();
|
|
755
|
+
await offlineBuffer.load();
|
|
756
|
+
if (offlineBuffer.size() > 0) {
|
|
757
|
+
const items = await offlineBuffer.drain();
|
|
758
|
+
for (const ev of items) {
|
|
759
|
+
offlineBuffer.push(ev);
|
|
760
|
+
}
|
|
761
|
+
sendEvent(config, {
|
|
762
|
+
level: "debug",
|
|
763
|
+
message: "[fixprompt] resumed from offline buffer",
|
|
764
|
+
attrs: { kind: "sdk.startup", buffered: items.length }
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
} catch (err) {
|
|
768
|
+
if (config.debug) {
|
|
769
|
+
console.warn(`[fixprompt] init async setup failed: ${err.message}`);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
})();
|
|
773
|
+
if (config.debug) {
|
|
774
|
+
console.log("[fixprompt] initialized", {
|
|
775
|
+
endpoint: config.endpoint,
|
|
776
|
+
service: config.service,
|
|
777
|
+
env: config.env,
|
|
778
|
+
session_id: state.sessionId
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
function captureException(err, options = {}) {
|
|
783
|
+
const state = getState();
|
|
784
|
+
if (!state.initialized || !state.config) return;
|
|
785
|
+
const isErr = err instanceof Error;
|
|
786
|
+
sendEvent(state.config, {
|
|
787
|
+
level: "error",
|
|
788
|
+
message: isErr ? err.message : String(err),
|
|
789
|
+
stack: isErr && typeof err.stack === "string" ? err.stack : void 0,
|
|
790
|
+
attrs: {
|
|
791
|
+
kind: "captureException",
|
|
792
|
+
severity: "error",
|
|
793
|
+
error_name: isErr ? err.name : typeof err,
|
|
794
|
+
...options.attrs ?? {}
|
|
795
|
+
},
|
|
796
|
+
synthetic: options.synthetic === true
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
function setUser(user) {
|
|
800
|
+
const state = getState();
|
|
801
|
+
state.user = user;
|
|
802
|
+
}
|
|
803
|
+
function _resetForTests() {
|
|
804
|
+
const state = getState();
|
|
805
|
+
state.cleanup.removeErrorHandler?.();
|
|
806
|
+
state.cleanup.removeRejectionHandler?.();
|
|
807
|
+
state.cleanup.restoreConsoleError?.();
|
|
808
|
+
state.cleanup.restoreConsoleWarn?.();
|
|
809
|
+
state.initialized = false;
|
|
810
|
+
state.config = null;
|
|
811
|
+
state.sessionId = null;
|
|
812
|
+
state.deviceId = null;
|
|
813
|
+
state.user = null;
|
|
814
|
+
state.cleanup = {};
|
|
815
|
+
}
|
|
816
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
817
|
+
0 && (module.exports = {
|
|
818
|
+
SDK_NAME,
|
|
819
|
+
SDK_VERSION,
|
|
820
|
+
_resetForTests,
|
|
821
|
+
captureException,
|
|
822
|
+
initFixPrompt,
|
|
823
|
+
setUser
|
|
824
|
+
});
|
|
825
|
+
//# sourceMappingURL=index.cjs.map
|