@webority-technologies/mobile-core 0.0.1 → 0.0.3
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 +22 -1
- package/lib/commonjs/api/baseUrl.js +34 -0
- package/lib/commonjs/api/curl.js +109 -0
- package/lib/commonjs/api/publicClient.js +11 -20
- package/lib/commonjs/api/retry.js +75 -0
- package/lib/commonjs/api/userClient.js +46 -22
- package/lib/commonjs/auth/authStore.js +101 -33
- package/lib/commonjs/auth/jwt.js +32 -8
- package/lib/commonjs/config/index.js +2 -1
- package/lib/commonjs/deepLink/index.js +286 -0
- package/lib/commonjs/download/adapters/expoFs.js +100 -0
- package/lib/commonjs/download/adapters/shared.js +13 -0
- package/lib/commonjs/download/index.js +272 -0
- package/lib/commonjs/formatters/date.js +1 -1
- package/lib/commonjs/formatters/index.js +24 -0
- package/lib/commonjs/formatters/phone.js +132 -15
- package/lib/commonjs/geolocation/adapters/expoLocation.js +126 -0
- package/lib/commonjs/geolocation/index.js +339 -0
- package/lib/commonjs/index.js +151 -48
- package/lib/commonjs/initSDK.js +23 -2
- package/lib/commonjs/initUserAuth.js +2 -1
- package/lib/commonjs/logger/index.js +159 -5
- package/lib/commonjs/network/index.js +6 -0
- package/lib/commonjs/network/networkStatus.js +50 -15
- package/lib/commonjs/permissions/index.js +24 -1
- package/lib/commonjs/sqlite/adapters/expo.js +53 -0
- package/lib/commonjs/sqlite/adapters/op.js +43 -0
- package/lib/commonjs/sqlite/adapters/rows.js +33 -0
- package/lib/commonjs/sqlite/adapters/storage.js +50 -0
- package/lib/commonjs/sqlite/adapters/sync.js +45 -0
- package/lib/commonjs/sqlite/index.js +610 -0
- package/lib/commonjs/sqlite/nitro.js +17 -0
- package/lib/commonjs/sqlite/op.js +18 -0
- package/lib/commonjs/sqlite/quick.js +14 -0
- package/lib/commonjs/sqlite/storage.js +14 -0
- package/lib/commonjs/storage/index.js +41 -20
- package/lib/commonjs/types/globals.d.js +6 -0
- package/lib/commonjs/utils/imageCompression.js +51 -14
- package/lib/commonjs/utils/index.js +6 -0
- package/lib/commonjs/versionCheck/index.js +28 -4
- package/lib/module/api/baseUrl.js +30 -0
- package/lib/module/api/curl.js +104 -0
- package/lib/module/api/publicClient.js +11 -20
- package/lib/module/api/retry.js +69 -0
- package/lib/module/api/userClient.js +45 -21
- package/lib/module/auth/authStore.js +99 -32
- package/lib/module/auth/jwt.js +32 -8
- package/lib/module/config/index.js +2 -1
- package/lib/module/deepLink/index.js +280 -0
- package/lib/module/download/adapters/expoFs.js +95 -0
- package/lib/module/download/adapters/shared.js +8 -0
- package/lib/module/download/index.js +264 -0
- package/lib/module/formatters/date.js +1 -1
- package/lib/module/formatters/index.js +1 -1
- package/lib/module/formatters/phone.js +110 -13
- package/lib/module/geolocation/adapters/expoLocation.js +121 -0
- package/lib/module/geolocation/index.js +332 -0
- package/lib/module/index.js +28 -11
- package/lib/module/initSDK.js +23 -2
- package/lib/module/initUserAuth.js +2 -1
- package/lib/module/logger/index.js +156 -4
- package/lib/module/network/index.js +1 -1
- package/lib/module/network/networkStatus.js +47 -14
- package/lib/module/permissions/index.js +22 -0
- package/lib/module/sqlite/adapters/expo.js +48 -0
- package/lib/module/sqlite/adapters/op.js +38 -0
- package/lib/module/sqlite/adapters/rows.js +28 -0
- package/lib/module/sqlite/adapters/storage.js +46 -0
- package/lib/module/sqlite/adapters/sync.js +41 -0
- package/lib/module/sqlite/index.js +600 -0
- package/lib/module/sqlite/nitro.js +12 -0
- package/lib/module/sqlite/op.js +13 -0
- package/lib/module/sqlite/quick.js +9 -0
- package/lib/module/sqlite/storage.js +9 -0
- package/lib/module/storage/index.js +38 -19
- package/lib/module/types/globals.d.js +10 -0
- package/lib/module/utils/imageCompression.js +49 -13
- package/lib/module/utils/index.js +1 -1
- package/lib/module/versionCheck/index.js +27 -4
- package/lib/typescript/commonjs/api/baseUrl.d.ts +20 -0
- package/lib/typescript/commonjs/api/curl.d.ts +18 -0
- package/lib/typescript/commonjs/api/retry.d.ts +27 -0
- package/lib/typescript/commonjs/api/userClient.d.ts +11 -0
- package/lib/typescript/commonjs/auth/authStore.d.ts +29 -6
- package/lib/typescript/commonjs/config/index.d.ts +6 -0
- package/lib/typescript/commonjs/deepLink/index.d.ts +54 -0
- package/lib/typescript/commonjs/download/adapters/expoFs.d.ts +45 -0
- package/lib/typescript/commonjs/download/adapters/shared.d.ts +3 -0
- package/lib/typescript/commonjs/download/index.d.ts +76 -0
- package/lib/typescript/commonjs/formatters/index.d.ts +2 -1
- package/lib/typescript/commonjs/formatters/phone.d.ts +27 -1
- package/lib/typescript/commonjs/geolocation/adapters/expoLocation.d.ts +42 -0
- package/lib/typescript/commonjs/geolocation/index.d.ts +89 -0
- package/lib/typescript/commonjs/index.d.ts +30 -13
- package/lib/typescript/commonjs/initSDK.d.ts +32 -0
- package/lib/typescript/commonjs/logger/index.d.ts +39 -0
- package/lib/typescript/commonjs/network/index.d.ts +2 -2
- package/lib/typescript/commonjs/network/networkStatus.d.ts +16 -0
- package/lib/typescript/commonjs/permissions/index.d.ts +35 -0
- package/lib/typescript/commonjs/sqlite/adapters/expo.d.ts +30 -0
- package/lib/typescript/commonjs/sqlite/adapters/op.d.ts +27 -0
- package/lib/typescript/commonjs/sqlite/adapters/rows.d.ts +7 -0
- package/lib/typescript/commonjs/sqlite/adapters/storage.d.ts +30 -0
- package/lib/typescript/commonjs/sqlite/adapters/sync.d.ts +31 -0
- package/lib/typescript/commonjs/sqlite/index.d.ts +121 -0
- package/lib/typescript/commonjs/sqlite/nitro.d.ts +7 -0
- package/lib/typescript/commonjs/sqlite/op.d.ts +8 -0
- package/lib/typescript/commonjs/sqlite/quick.d.ts +4 -0
- package/lib/typescript/commonjs/sqlite/storage.d.ts +4 -0
- package/lib/typescript/commonjs/storage/index.d.ts +25 -3
- package/lib/typescript/commonjs/utils/imageCompression.d.ts +17 -0
- package/lib/typescript/commonjs/utils/index.d.ts +2 -2
- package/lib/typescript/module/api/baseUrl.d.ts +20 -0
- package/lib/typescript/module/api/curl.d.ts +18 -0
- package/lib/typescript/module/api/retry.d.ts +27 -0
- package/lib/typescript/module/api/userClient.d.ts +11 -0
- package/lib/typescript/module/auth/authStore.d.ts +29 -6
- package/lib/typescript/module/config/index.d.ts +6 -0
- package/lib/typescript/module/deepLink/index.d.ts +54 -0
- package/lib/typescript/module/download/adapters/expoFs.d.ts +45 -0
- package/lib/typescript/module/download/adapters/shared.d.ts +3 -0
- package/lib/typescript/module/download/index.d.ts +76 -0
- package/lib/typescript/module/formatters/index.d.ts +2 -1
- package/lib/typescript/module/formatters/phone.d.ts +27 -1
- package/lib/typescript/module/geolocation/adapters/expoLocation.d.ts +42 -0
- package/lib/typescript/module/geolocation/index.d.ts +89 -0
- package/lib/typescript/module/index.d.ts +30 -13
- package/lib/typescript/module/initSDK.d.ts +32 -0
- package/lib/typescript/module/logger/index.d.ts +39 -0
- package/lib/typescript/module/network/index.d.ts +2 -2
- package/lib/typescript/module/network/networkStatus.d.ts +16 -0
- package/lib/typescript/module/permissions/index.d.ts +35 -0
- package/lib/typescript/module/sqlite/adapters/expo.d.ts +30 -0
- package/lib/typescript/module/sqlite/adapters/op.d.ts +27 -0
- package/lib/typescript/module/sqlite/adapters/rows.d.ts +7 -0
- package/lib/typescript/module/sqlite/adapters/storage.d.ts +30 -0
- package/lib/typescript/module/sqlite/adapters/sync.d.ts +31 -0
- package/lib/typescript/module/sqlite/index.d.ts +121 -0
- package/lib/typescript/module/sqlite/nitro.d.ts +7 -0
- package/lib/typescript/module/sqlite/op.d.ts +8 -0
- package/lib/typescript/module/sqlite/quick.d.ts +4 -0
- package/lib/typescript/module/sqlite/storage.d.ts +4 -0
- package/lib/typescript/module/storage/index.d.ts +25 -3
- package/lib/typescript/module/utils/imageCompression.d.ts +17 -0
- package/lib/typescript/module/utils/index.d.ts +2 -2
- package/package.json +102 -13
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.setRemoteLogger = exports.Logger = void 0;
|
|
6
|
+
exports.setRemoteLogger = exports.setDeviceContext = exports.getDeviceContext = exports.configureLogger = exports.Logger = void 0;
|
|
7
7
|
var _index = require("../config/index.js");
|
|
8
8
|
// ANSI color codes
|
|
9
9
|
const Colors = {
|
|
@@ -76,6 +76,139 @@ const toErrorObject = input => {
|
|
|
76
76
|
return new Error(String(input));
|
|
77
77
|
}
|
|
78
78
|
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Device / app context attached once at boot (platform, OS version, app version,
|
|
82
|
+
* build number, device model, etc). Merged into every `recordError` context so
|
|
83
|
+
* every crash carries it without every call site repeating it.
|
|
84
|
+
*/
|
|
85
|
+
|
|
86
|
+
let deviceContext = null;
|
|
87
|
+
const normalizeAttributeValue = value => {
|
|
88
|
+
if (value === null || value === undefined) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
92
|
+
return value;
|
|
93
|
+
}
|
|
94
|
+
return String(value);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Set (or clear, with `null`) the device/app context merged into every
|
|
99
|
+
* `recordError` call. Each key is also forwarded to `remote.setAttribute`
|
|
100
|
+
* once, at the moment it is set.
|
|
101
|
+
*/
|
|
102
|
+
const setDeviceContext = context => {
|
|
103
|
+
deviceContext = context;
|
|
104
|
+
if (context) {
|
|
105
|
+
for (const [key, value] of Object.entries(context)) {
|
|
106
|
+
safe(() => remote?.setAttribute?.(key, normalizeAttributeValue(value)));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
exports.setDeviceContext = setDeviceContext;
|
|
111
|
+
const getDeviceContext = () => deviceContext;
|
|
112
|
+
|
|
113
|
+
/** Tuning knobs for screen history and duplicate-error suppression. */
|
|
114
|
+
exports.getDeviceContext = getDeviceContext;
|
|
115
|
+
const DEFAULT_LOGGER_OPTIONS = {
|
|
116
|
+
dedupeWindowMs: 5000,
|
|
117
|
+
dedupeMaxPerWindow: 1,
|
|
118
|
+
screenHistoryLimit: 20
|
|
119
|
+
};
|
|
120
|
+
let loggerOptions = {
|
|
121
|
+
...DEFAULT_LOGGER_OPTIONS
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/** Configure dedupe window/threshold and screen history size. Merges with current options. */
|
|
125
|
+
const configureLogger = options => {
|
|
126
|
+
loggerOptions = {
|
|
127
|
+
...loggerOptions,
|
|
128
|
+
...options
|
|
129
|
+
};
|
|
130
|
+
if (screenHistory.length > loggerOptions.screenHistoryLimit) {
|
|
131
|
+
screenHistory = screenHistory.slice(screenHistory.length - loggerOptions.screenHistoryLimit);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
exports.configureLogger = configureLogger;
|
|
135
|
+
let currentScreen = null;
|
|
136
|
+
let screenHistory = [];
|
|
137
|
+
const dedupeMap = new Map();
|
|
138
|
+
const MAX_DEDUPE_ENTRIES = 200;
|
|
139
|
+
const dedupeKeyFor = err => {
|
|
140
|
+
const firstFrame = err.stack?.split('\n')[1]?.trim();
|
|
141
|
+
return firstFrame ? `${err.message}::${firstFrame}` : err.message;
|
|
142
|
+
};
|
|
143
|
+
const capDedupeMap = () => {
|
|
144
|
+
while (dedupeMap.size > MAX_DEDUPE_ENTRIES) {
|
|
145
|
+
const oldestKey = dedupeMap.keys().next().value;
|
|
146
|
+
if (oldestKey === undefined) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
dedupeMap.delete(oldestKey);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
const shouldForward = key => {
|
|
153
|
+
if (loggerOptions.dedupeWindowMs <= 0) {
|
|
154
|
+
return {
|
|
155
|
+
forward: true
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
const now = Date.now();
|
|
159
|
+
const entry = dedupeMap.get(key);
|
|
160
|
+
if (!entry || now - entry.windowStart >= loggerOptions.dedupeWindowMs) {
|
|
161
|
+
const suppressedCount = entry?.suppressedCount ?? 0;
|
|
162
|
+
dedupeMap.set(key, {
|
|
163
|
+
windowStart: now,
|
|
164
|
+
count: 1,
|
|
165
|
+
suppressedCount: 0
|
|
166
|
+
});
|
|
167
|
+
capDedupeMap();
|
|
168
|
+
return suppressedCount > 0 ? {
|
|
169
|
+
forward: true,
|
|
170
|
+
suppressedCount
|
|
171
|
+
} : {
|
|
172
|
+
forward: true
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
entry.count += 1;
|
|
176
|
+
if (entry.count > loggerOptions.dedupeMaxPerWindow) {
|
|
177
|
+
entry.suppressedCount += 1;
|
|
178
|
+
return {
|
|
179
|
+
forward: false
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
forward: true
|
|
184
|
+
};
|
|
185
|
+
};
|
|
186
|
+
const buildErrorContext = (context, suppressedCount) => {
|
|
187
|
+
const merged = {
|
|
188
|
+
...deviceContext
|
|
189
|
+
};
|
|
190
|
+
if (currentScreen !== null) {
|
|
191
|
+
merged.screen = currentScreen;
|
|
192
|
+
}
|
|
193
|
+
if (suppressedCount) {
|
|
194
|
+
merged.suppressedCount = suppressedCount;
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
...merged,
|
|
198
|
+
...context
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
const forwardErrorToRemote = (err, context) => {
|
|
202
|
+
const key = dedupeKeyFor(err);
|
|
203
|
+
const {
|
|
204
|
+
forward,
|
|
205
|
+
suppressedCount
|
|
206
|
+
} = shouldForward(key);
|
|
207
|
+
if (!forward) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
safe(() => remote?.recordError?.(err, buildErrorContext(context, suppressedCount)));
|
|
211
|
+
};
|
|
79
212
|
const logInfo = (message, ...optionalParams) => {
|
|
80
213
|
if (!isEnabled() || !isLogLevelAllowed(LogLevels.INFO.level)) {
|
|
81
214
|
return;
|
|
@@ -100,10 +233,10 @@ const logError = (message, ...optionalParams) => {
|
|
|
100
233
|
// First optional param is treated as the underlying error if it looks like one.
|
|
101
234
|
const candidate = optionalParams[0];
|
|
102
235
|
if (candidate !== undefined) {
|
|
103
|
-
|
|
236
|
+
forwardErrorToRemote(toErrorObject(candidate), {
|
|
104
237
|
source: 'Logger.error',
|
|
105
238
|
message
|
|
106
|
-
})
|
|
239
|
+
});
|
|
107
240
|
}
|
|
108
241
|
};
|
|
109
242
|
const breadcrumb = (message, data) => {
|
|
@@ -117,7 +250,7 @@ const recordError = (error, context) => {
|
|
|
117
250
|
if (isEnabled() && isLogLevelAllowed('error')) {
|
|
118
251
|
console.error(`${Colors.RED_BOLD}[RECORDED]: ${err.message}${Colors.RESET}`, context ?? '');
|
|
119
252
|
}
|
|
120
|
-
|
|
253
|
+
forwardErrorToRemote(err, context);
|
|
121
254
|
};
|
|
122
255
|
const setUser = (id, attrs) => {
|
|
123
256
|
safe(() => remote?.setUser?.(id, attrs));
|
|
@@ -125,6 +258,24 @@ const setUser = (id, attrs) => {
|
|
|
125
258
|
const setAttribute = (key, value) => {
|
|
126
259
|
safe(() => remote?.setAttribute?.(key, value));
|
|
127
260
|
};
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Record the active screen as a breadcrumb and remember it for subsequent
|
|
264
|
+
* `recordError` context. Re-tracking the same screen name is a no-op.
|
|
265
|
+
*/
|
|
266
|
+
const trackScreen = (name, params) => {
|
|
267
|
+
if (name === currentScreen) {
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
currentScreen = name;
|
|
271
|
+
screenHistory.push(name);
|
|
272
|
+
if (screenHistory.length > loggerOptions.screenHistoryLimit) {
|
|
273
|
+
screenHistory = screenHistory.slice(screenHistory.length - loggerOptions.screenHistoryLimit);
|
|
274
|
+
}
|
|
275
|
+
breadcrumb(`Screen: ${name}`, params);
|
|
276
|
+
};
|
|
277
|
+
const getCurrentScreen = () => currentScreen;
|
|
278
|
+
const getScreenHistory = () => [...screenHistory];
|
|
128
279
|
const Logger = exports.Logger = {
|
|
129
280
|
info: logInfo,
|
|
130
281
|
warn: logWarning,
|
|
@@ -132,6 +283,9 @@ const Logger = exports.Logger = {
|
|
|
132
283
|
breadcrumb,
|
|
133
284
|
recordError,
|
|
134
285
|
setUser,
|
|
135
|
-
setAttribute
|
|
286
|
+
setAttribute,
|
|
287
|
+
trackScreen,
|
|
288
|
+
getCurrentScreen,
|
|
289
|
+
getScreenHistory
|
|
136
290
|
};
|
|
137
291
|
//# sourceMappingURL=index.js.map
|
|
@@ -15,6 +15,12 @@ Object.defineProperty(exports, "getNetworkStatus", {
|
|
|
15
15
|
return _networkStatus.getNetworkStatus;
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
+
Object.defineProperty(exports, "setNetworkStatusImplementation", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _networkStatus.setNetworkStatusImplementation;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
18
24
|
Object.defineProperty(exports, "useNetworkStatus", {
|
|
19
25
|
enumerable: true,
|
|
20
26
|
get: function () {
|
|
@@ -3,29 +3,64 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.useNetworkStatus = exports.getNetworkStatus = exports.addNetworkStatusListener = void 0;
|
|
6
|
+
exports.useNetworkStatus = exports.setNetworkStatusImplementation = exports.getNetworkStatus = exports.addNetworkStatusListener = void 0;
|
|
7
|
+
var ExpoNetwork = _interopRequireWildcard(require("expo-network"));
|
|
7
8
|
var _react = require("react");
|
|
8
9
|
var _index = require("../logger/index.js");
|
|
10
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
9
11
|
const DEFAULT_STATUS = {
|
|
10
12
|
isConnected: true,
|
|
11
13
|
isInternetReachable: null,
|
|
12
14
|
type: 'unknown'
|
|
13
15
|
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
/**
|
|
17
|
+
* expo-network is imported directly, not resolved through a seam.
|
|
18
|
+
*
|
|
19
|
+
* `expo` is a REQUIRED peer of this package, so every consumer has the Expo
|
|
20
|
+
* modules by construction and the static-require problem that forced the old
|
|
21
|
+
* injection design does not arise. An app wires nothing: connectivity works
|
|
22
|
+
* because the library uses Expo, which is the point of the Expo-first policy.
|
|
23
|
+
* One backend also means one behaviour, rather than each app choosing.
|
|
24
|
+
*/
|
|
25
|
+
let override = null;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Replace the backend. Intended for TESTS and for the showcase, which uses it
|
|
29
|
+
* to reach error paths that a healthy device never takes; it is not the way an
|
|
30
|
+
* app is meant to configure the library. Pass `null` to restore expo-network.
|
|
31
|
+
*/
|
|
32
|
+
const setNetworkStatusImplementation = impl => {
|
|
33
|
+
override = impl;
|
|
34
|
+
};
|
|
35
|
+
exports.setNetworkStatusImplementation = setNetworkStatusImplementation;
|
|
36
|
+
const resolveNetInfo = () => override ?? expoNetworkBackend;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* expo-network in the shape this module already speaks.
|
|
40
|
+
*
|
|
41
|
+
* The conversion is not cosmetic: expo reports its type as an UPPERCASE enum
|
|
42
|
+
* where this module's vocabulary is lowercase, marks every field optional, and
|
|
43
|
+
* returns an EventSubscription where an unsubscribe function is expected.
|
|
44
|
+
*/
|
|
45
|
+
const expoNetworkBackend = {
|
|
46
|
+
fetch: async () => {
|
|
47
|
+
const state = await ExpoNetwork.getNetworkStateAsync();
|
|
48
|
+
return {
|
|
49
|
+
isConnected: state?.isConnected !== false,
|
|
50
|
+
isInternetReachable: state?.isInternetReachable ?? null,
|
|
51
|
+
type: state?.type ? String(state.type).toLowerCase() : undefined
|
|
52
|
+
};
|
|
53
|
+
},
|
|
54
|
+
addEventListener: cb => {
|
|
55
|
+
const subscription = ExpoNetwork.addNetworkStateListener(state => {
|
|
56
|
+
cb({
|
|
57
|
+
isConnected: state?.isConnected !== false,
|
|
58
|
+
isInternetReachable: state?.isInternetReachable ?? null,
|
|
59
|
+
type: state?.type ? String(state.type).toLowerCase() : undefined
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
return () => subscription.remove();
|
|
27
63
|
}
|
|
28
|
-
return netInfo;
|
|
29
64
|
};
|
|
30
65
|
const normalize = state => {
|
|
31
66
|
if (!state) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.Permissions = void 0;
|
|
6
|
+
exports.setPermissionsImplementation = exports.Permissions = void 0;
|
|
7
7
|
var _reactNative = require("react-native");
|
|
8
8
|
var _index = require("../logger/index.js");
|
|
9
9
|
// Android only — legacy WRITE_EXTERNAL_STORAGE
|
|
@@ -24,6 +24,29 @@ const resolveModule = () => {
|
|
|
24
24
|
}
|
|
25
25
|
return permsModule;
|
|
26
26
|
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Inject a custom permissions implementation at runtime.
|
|
30
|
+
* Pass `null` to reset to the default lazily-resolved native module.
|
|
31
|
+
*
|
|
32
|
+
* `resolved` goes FALSE on null, never true. Marking it resolved with a null
|
|
33
|
+
* backend would permanently disable permissions: the resolver short-circuits and the
|
|
34
|
+
* real module is never loaded again, which contradicts this function's own
|
|
35
|
+
* documented contract. That exact bug shipped once, in the storage seam.
|
|
36
|
+
*
|
|
37
|
+
* THIS MODULE IS THE EXPO-FIRST EXCEPTION, and deliberately keeps the old
|
|
38
|
+
* shape. Expo ships no permissions package: each module carries its own
|
|
39
|
+
* (expo-location's requestForegroundPermissionsAsync, expo-image-picker's, and
|
|
40
|
+
* so on), so there is no single object to adapt and the library must not guess
|
|
41
|
+
* which Expo modules an app installed. react-native-permissions stays, behind
|
|
42
|
+
* this module's own import path so an app that never asks for permissions
|
|
43
|
+
* never names the package to Metro.
|
|
44
|
+
*/
|
|
45
|
+
const setPermissionsImplementation = impl => {
|
|
46
|
+
permsModule = impl;
|
|
47
|
+
resolved = impl !== null;
|
|
48
|
+
};
|
|
49
|
+
exports.setPermissionsImplementation = setPermissionsImplementation;
|
|
27
50
|
const mapToNative = kind => {
|
|
28
51
|
const m = resolveModule();
|
|
29
52
|
if (!m) {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.adaptExpoSqlite = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* expo-sqlite. Shape verified against 57.0.2 rather than assumed, and it is the
|
|
9
|
+
* one driver that cannot share an adapter with the others: expo splits reads
|
|
10
|
+
* from writes. `getAllAsync` yields rows but no change count, `runAsync` yields
|
|
11
|
+
* `{ changes, lastInsertRowId }` but no rows, and SqliteResultSet needs all
|
|
12
|
+
* three from one call. `prepareAsync` + `executeAsync` is the only call that
|
|
13
|
+
* returns both, so every statement goes through it rather than being routed by
|
|
14
|
+
* sniffing the SQL for a leading SELECT.
|
|
15
|
+
*
|
|
16
|
+
* The REQUIRE lives in the driver entry point beside this file, never here.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const adaptExpoSqlite = mod => ({
|
|
20
|
+
// expo takes the directory as a third positional argument rather than an
|
|
21
|
+
// option, so `location` cannot be passed through the options object.
|
|
22
|
+
open: async (name, options) => {
|
|
23
|
+
const db = await mod.openDatabaseAsync(name, undefined, options?.location);
|
|
24
|
+
return {
|
|
25
|
+
execute: async (sql, params) => {
|
|
26
|
+
const statement = await db.prepareAsync(sql);
|
|
27
|
+
try {
|
|
28
|
+
const result = await statement.executeAsync(params ? [...params] : []);
|
|
29
|
+
// Safe on a write: expo returns [] when the statement produced no
|
|
30
|
+
// first row rather than stepping the statement a second time.
|
|
31
|
+
const rows = await result.getAllAsync();
|
|
32
|
+
return {
|
|
33
|
+
rows,
|
|
34
|
+
rowsAffected: result.changes,
|
|
35
|
+
// expo always reports lastInsertRowId, so unlike the other drivers
|
|
36
|
+
// this is never undefined. It is the connection's last insert rowid,
|
|
37
|
+
// which is only meaningful immediately after an INSERT.
|
|
38
|
+
insertId: result.lastInsertRowId
|
|
39
|
+
};
|
|
40
|
+
} finally {
|
|
41
|
+
// A statement left unfinalised holds a native handle for the life of
|
|
42
|
+
// the connection, and the core executes one per call.
|
|
43
|
+
await statement.finalizeAsync();
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
close: async () => {
|
|
47
|
+
await db.closeAsync();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
exports.adaptExpoSqlite = adaptExpoSqlite;
|
|
53
|
+
//# sourceMappingURL=expo.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.adaptOpSqlite = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* @op-engineering/op-sqlite. Shape verified against 18.1.4 rather than assumed:
|
|
9
|
+
* `open({ name, location })` is synchronous and returns a DB whose `execute` is
|
|
10
|
+
* ASYNC, and whose `rows` is already a plain array of objects rather than the
|
|
11
|
+
* `{ _array, item() }` shape the older drivers use. Both differences are why it
|
|
12
|
+
* cannot share the sync adapter.
|
|
13
|
+
*
|
|
14
|
+
* The REQUIRE lives in the driver entry point beside this file, never here.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const adaptOpSqlite = mod => ({
|
|
18
|
+
open: async (name, options) => {
|
|
19
|
+
const db = mod.open({
|
|
20
|
+
name,
|
|
21
|
+
location: options?.location
|
|
22
|
+
});
|
|
23
|
+
return {
|
|
24
|
+
execute: async (sql, params) => {
|
|
25
|
+
const result = await db.execute(sql, params ? [...params] : undefined);
|
|
26
|
+
return {
|
|
27
|
+
rows: result.rows ?? [],
|
|
28
|
+
rowsAffected: result.rowsAffected ?? 0,
|
|
29
|
+
insertId: result.insertId
|
|
30
|
+
};
|
|
31
|
+
},
|
|
32
|
+
close: async () => {
|
|
33
|
+
if (db.closeAsync) {
|
|
34
|
+
await db.closeAsync();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
db.close();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
exports.adaptOpSqlite = adaptOpSqlite;
|
|
43
|
+
//# sourceMappingURL=op.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.rowsToArray = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Row shapes differ per driver: a plain array, `{ _array, length, item() }`, or
|
|
9
|
+
* `{ length, item() }` alone. Every adapter normalises to a plain array here so
|
|
10
|
+
* nothing driver-specific escapes into the Db layer.
|
|
11
|
+
*/
|
|
12
|
+
const rowsToArray = rows => {
|
|
13
|
+
if (Array.isArray(rows)) {
|
|
14
|
+
return rows;
|
|
15
|
+
}
|
|
16
|
+
const shaped = rows;
|
|
17
|
+
if (!shaped) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
if (Array.isArray(shaped._array)) {
|
|
21
|
+
return shaped._array;
|
|
22
|
+
}
|
|
23
|
+
if (typeof shaped.item === 'function' && typeof shaped.length === 'number') {
|
|
24
|
+
const out = [];
|
|
25
|
+
for (let i = 0; i < shaped.length; i += 1) {
|
|
26
|
+
out.push(shaped.item(i));
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
return [];
|
|
31
|
+
};
|
|
32
|
+
exports.rowsToArray = rowsToArray;
|
|
33
|
+
//# sourceMappingURL=rows.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.adaptSqliteStorage = void 0;
|
|
7
|
+
var _rows = require("./rows.js");
|
|
8
|
+
/** react-native-sqlite-storage: callback-based by default, promise-based once
|
|
9
|
+
* `enablePromise(true)` is called; `executeSql` resolves an array whose first
|
|
10
|
+
* element is the result set. */
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Adapt an already-required `react-native-sqlite-storage` module. Exported for
|
|
14
|
+
* the same reason as the filesystem adapters: the library cannot name a package
|
|
15
|
+
* the app did not install without breaking the app's bundle.
|
|
16
|
+
*/
|
|
17
|
+
const adaptSqliteStorage = mod => ({
|
|
18
|
+
open: async (name, options) => {
|
|
19
|
+
// This is a GLOBAL side effect, not a per-connection setting: the vendor
|
|
20
|
+
// implements it by rewriting SQLitePlugin and SQLiteFactory prototype
|
|
21
|
+
// methods. An app that also uses react-native-sqlite-storage directly in
|
|
22
|
+
// callback mode will find its own callbacks converted to promises from the
|
|
23
|
+
// moment this adapter opens a database. Unavoidable, since the adapter
|
|
24
|
+
// cannot work otherwise, and worth knowing before mixing the two.
|
|
25
|
+
mod.enablePromise(true);
|
|
26
|
+
const db = await mod.openDatabase({
|
|
27
|
+
name,
|
|
28
|
+
location: options?.location ?? 'default'
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
execute: async (sql, params) => {
|
|
32
|
+
const [result] = await db.executeSql(sql, params ? [...params] : undefined);
|
|
33
|
+
return {
|
|
34
|
+
rows: (0, _rows.rowsToArray)(result.rows),
|
|
35
|
+
rowsAffected: result.rowsAffected ?? 0,
|
|
36
|
+
insertId: result.insertId
|
|
37
|
+
};
|
|
38
|
+
},
|
|
39
|
+
// Not `() => db.close()`: in promise mode this driver resolves the
|
|
40
|
+
// success-callback ARGUMENTS array rather than void, so returning it
|
|
41
|
+
// directly would make SqliteDatabase.close() resolve an array while
|
|
42
|
+
// typed as void. Awaiting and discarding makes the type honest.
|
|
43
|
+
close: async () => {
|
|
44
|
+
await db.close();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
exports.adaptSqliteStorage = adaptSqliteStorage;
|
|
50
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.adaptSyncSqlite = void 0;
|
|
7
|
+
var _rows = require("./rows.js");
|
|
8
|
+
/**
|
|
9
|
+
* nitro-sqlite and quick-sqlite share one synchronous shape, so one adapter
|
|
10
|
+
* serves both. The REQUIRE lives in the driver entry points beside this file,
|
|
11
|
+
* never here and never in the core: Metro resolves requires statically, so a
|
|
12
|
+
* package named anywhere reachable becomes mandatory for every consumer.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Shape shared by react-native-nitro-sqlite and react-native-quick-sqlite: a
|
|
16
|
+
* synchronous `open({ name, location })` whose `db.execute()` and `db.close()`
|
|
17
|
+
* are also synchronous. Both are wrapped in Promise.resolve to fit SqliteDriver. */
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Adapt an already-required nitro-sqlite or quick-sqlite module. Both expose the
|
|
21
|
+
* same synchronous shape. Exported so an app on quick-sqlite can inject it.
|
|
22
|
+
*/
|
|
23
|
+
const adaptSyncSqlite = mod => ({
|
|
24
|
+
open: async (name, options) => {
|
|
25
|
+
const db = mod.open({
|
|
26
|
+
name,
|
|
27
|
+
location: options?.location
|
|
28
|
+
});
|
|
29
|
+
return {
|
|
30
|
+
execute: async (sql, params) => {
|
|
31
|
+
const result = db.execute(sql, params ? [...params] : undefined);
|
|
32
|
+
return {
|
|
33
|
+
rows: (0, _rows.rowsToArray)(result.rows),
|
|
34
|
+
rowsAffected: result.rowsAffected ?? 0,
|
|
35
|
+
insertId: result.insertId
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
close: async () => {
|
|
39
|
+
db.close();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
exports.adaptSyncSqlite = adaptSyncSqlite;
|
|
45
|
+
//# sourceMappingURL=sync.js.map
|