@fto-consult/expo-ui 6.37.3 → 6.37.5

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 (114) hide show
  1. package/App.js +0 -1
  2. package/node_modules/.package-lock.json +26218 -26188
  3. package/node_modules/@fto-consult/common/babel.config.alias.js +18 -1
  4. package/node_modules/@fto-consult/common/package.json +1 -1
  5. package/node_modules/@react-native-async-storage/async-storage/LICENSE +21 -0
  6. package/node_modules/@react-native-async-storage/async-storage/README.md +27 -0
  7. package/node_modules/@react-native-async-storage/async-storage/RNCAsyncStorage.podspec +19 -0
  8. package/node_modules/@react-native-async-storage/async-storage/android/build.gradle +142 -0
  9. package/node_modules/@react-native-async-storage/async-storage/android/src/main/AndroidManifest.xml +6 -0
  10. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncLocalStorageUtil.java +178 -0
  11. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageErrorUtil.java +45 -0
  12. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageExpoMigration.java +154 -0
  13. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageModule.java +424 -0
  14. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStoragePackage.java +58 -0
  15. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/ReactDatabaseSupplier.java +163 -0
  16. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/SerialExecutor.java +40 -0
  17. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/next/ArgumentHelpers.kt +86 -0
  18. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/next/ErrorHelpers.kt +39 -0
  19. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/next/StorageModule.kt +90 -0
  20. package/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/next/StorageSupplier.kt +161 -0
  21. package/node_modules/@react-native-async-storage/async-storage/android/src/test/java/com/reactnativecommunity/asyncstorage/next/ArgumentHelpersTest.kt +93 -0
  22. package/node_modules/@react-native-async-storage/async-storage/android/src/test/java/com/reactnativecommunity/asyncstorage/next/StorageTest.kt +141 -0
  23. package/node_modules/@react-native-async-storage/async-storage/android/testresults.gradle +38 -0
  24. package/node_modules/@react-native-async-storage/async-storage/ios/RNCAsyncStorage.h +51 -0
  25. package/node_modules/@react-native-async-storage/async-storage/ios/RNCAsyncStorage.m +898 -0
  26. package/node_modules/@react-native-async-storage/async-storage/ios/RNCAsyncStorage.xcodeproj/project.pbxproj +283 -0
  27. package/node_modules/@react-native-async-storage/async-storage/ios/RNCAsyncStorageDelegate.h +73 -0
  28. package/node_modules/@react-native-async-storage/async-storage/jest/async-storage-mock.d.ts +9 -0
  29. package/node_modules/@react-native-async-storage/async-storage/jest/async-storage-mock.js +109 -0
  30. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/AsyncStorage.js +164 -0
  31. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/AsyncStorage.js.map +1 -0
  32. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/AsyncStorage.native.js +366 -0
  33. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/AsyncStorage.native.js.map +1 -0
  34. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/RCTAsyncStorage.js +30 -0
  35. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/RCTAsyncStorage.js.map +1 -0
  36. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/helpers.js +69 -0
  37. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/helpers.js.map +1 -0
  38. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/hooks.js +44 -0
  39. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/hooks.js.map +1 -0
  40. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/index.js +22 -0
  41. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/index.js.map +1 -0
  42. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/shouldFallbackToLegacyNativeModule.js +39 -0
  43. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/shouldFallbackToLegacyNativeModule.js.map +1 -0
  44. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/types.js +2 -0
  45. package/node_modules/@react-native-async-storage/async-storage/lib/commonjs/types.js.map +1 -0
  46. package/node_modules/@react-native-async-storage/async-storage/lib/module/AsyncStorage.js +153 -0
  47. package/node_modules/@react-native-async-storage/async-storage/lib/module/AsyncStorage.js.map +1 -0
  48. package/node_modules/@react-native-async-storage/async-storage/lib/module/AsyncStorage.native.js +348 -0
  49. package/node_modules/@react-native-async-storage/async-storage/lib/module/AsyncStorage.native.js.map +1 -0
  50. package/node_modules/@react-native-async-storage/async-storage/lib/module/RCTAsyncStorage.js +20 -0
  51. package/node_modules/@react-native-async-storage/async-storage/lib/module/RCTAsyncStorage.js.map +1 -0
  52. package/node_modules/@react-native-async-storage/async-storage/lib/module/helpers.js +56 -0
  53. package/node_modules/@react-native-async-storage/async-storage/lib/module/helpers.js.map +1 -0
  54. package/node_modules/@react-native-async-storage/async-storage/lib/module/hooks.js +34 -0
  55. package/node_modules/@react-native-async-storage/async-storage/lib/module/hooks.js.map +1 -0
  56. package/node_modules/@react-native-async-storage/async-storage/lib/module/index.js +4 -0
  57. package/node_modules/@react-native-async-storage/async-storage/lib/module/index.js.map +1 -0
  58. package/node_modules/@react-native-async-storage/async-storage/lib/module/shouldFallbackToLegacyNativeModule.js +31 -0
  59. package/node_modules/@react-native-async-storage/async-storage/lib/module/shouldFallbackToLegacyNativeModule.js.map +1 -0
  60. package/node_modules/@react-native-async-storage/async-storage/lib/module/types.js +2 -0
  61. package/node_modules/@react-native-async-storage/async-storage/lib/module/types.js.map +1 -0
  62. package/node_modules/@react-native-async-storage/async-storage/lib/typescript/AsyncStorage.d.ts +10 -0
  63. package/node_modules/@react-native-async-storage/async-storage/lib/typescript/AsyncStorage.native.d.ts +16 -0
  64. package/node_modules/@react-native-async-storage/async-storage/lib/typescript/RCTAsyncStorage.d.ts +2 -0
  65. package/node_modules/@react-native-async-storage/async-storage/lib/typescript/helpers.d.ts +5 -0
  66. package/node_modules/@react-native-async-storage/async-storage/lib/typescript/hooks.d.ts +2 -0
  67. package/node_modules/@react-native-async-storage/async-storage/lib/typescript/index.d.ts +4 -0
  68. package/node_modules/@react-native-async-storage/async-storage/lib/typescript/shouldFallbackToLegacyNativeModule.d.ts +1 -0
  69. package/node_modules/@react-native-async-storage/async-storage/lib/typescript/types.d.ts +113 -0
  70. package/node_modules/@react-native-async-storage/async-storage/macos/RNCAsyncStorage.xcodeproj/project.pbxproj +385 -0
  71. package/node_modules/@react-native-async-storage/async-storage/macos/RNCAsyncStorage.xcodeproj/xcshareddata/xcschemes/RNCAsyncStorage-macOS.xcscheme +67 -0
  72. package/node_modules/@react-native-async-storage/async-storage/macos/RNCAsyncStorage.xcodeproj/xcshareddata/xcschemes/RNCAsyncStorage.xcscheme +67 -0
  73. package/node_modules/@react-native-async-storage/async-storage/package.json +197 -0
  74. package/node_modules/@react-native-async-storage/async-storage/src/AsyncStorage.native.ts +356 -0
  75. package/node_modules/@react-native-async-storage/async-storage/src/AsyncStorage.ts +173 -0
  76. package/node_modules/@react-native-async-storage/async-storage/src/RCTAsyncStorage.ts +28 -0
  77. package/node_modules/@react-native-async-storage/async-storage/src/helpers.ts +74 -0
  78. package/node_modules/@react-native-async-storage/async-storage/src/hooks.ts +11 -0
  79. package/node_modules/@react-native-async-storage/async-storage/src/index.ts +7 -0
  80. package/node_modules/@react-native-async-storage/async-storage/src/shouldFallbackToLegacyNativeModule.ts +34 -0
  81. package/node_modules/@react-native-async-storage/async-storage/src/types.ts +155 -0
  82. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage/PropertySheet.props +16 -0
  83. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage/ReactNativeAsyncStorage.vcxproj +172 -0
  84. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage/ReactNativeAsyncStorage.vcxproj.filters +34 -0
  85. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage/packages.config +4 -0
  86. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage.sln +172 -0
  87. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage61/PropertySheet.props +16 -0
  88. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage61/ReactNativeAsyncStorage61.vcxproj +157 -0
  89. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage61/ReactNativeAsyncStorage61.vcxproj.filters +34 -0
  90. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage61/packages.config +4 -0
  91. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage61.sln +195 -0
  92. package/node_modules/@react-native-async-storage/async-storage/windows/ReactNativeAsyncStorage62.sln +192 -0
  93. package/node_modules/@react-native-async-storage/async-storage/windows/code/DBStorage.cpp +599 -0
  94. package/node_modules/@react-native-async-storage/async-storage/windows/code/DBStorage.h +162 -0
  95. package/node_modules/@react-native-async-storage/async-storage/windows/code/RNCAsyncStorage.h +118 -0
  96. package/node_modules/@react-native-async-storage/async-storage/windows/code/ReactNativeAsyncStorage.def +3 -0
  97. package/node_modules/@react-native-async-storage/async-storage/windows/code/ReactPackageProvider.cpp +20 -0
  98. package/node_modules/@react-native-async-storage/async-storage/windows/code/ReactPackageProvider.h +23 -0
  99. package/node_modules/@react-native-async-storage/async-storage/windows/code/ReactPackageProvider.idl +7 -0
  100. package/node_modules/@react-native-async-storage/async-storage/windows/code/pch.cpp +3 -0
  101. package/node_modules/@react-native-async-storage/async-storage/windows/code/pch.h +15 -0
  102. package/node_modules/merge-options/index.d.ts +2 -0
  103. package/node_modules/merge-options/index.js +171 -0
  104. package/node_modules/merge-options/index.mjs +8 -0
  105. package/node_modules/merge-options/license +21 -0
  106. package/node_modules/merge-options/node_modules/is-plain-obj/index.d.ts +29 -0
  107. package/node_modules/merge-options/node_modules/is-plain-obj/index.js +10 -0
  108. package/node_modules/merge-options/node_modules/is-plain-obj/license +9 -0
  109. package/node_modules/merge-options/node_modules/is-plain-obj/package.json +38 -0
  110. package/node_modules/merge-options/node_modules/is-plain-obj/readme.md +54 -0
  111. package/node_modules/merge-options/package.json +59 -0
  112. package/node_modules/merge-options/readme.md +130 -0
  113. package/package.json +131 -130
  114. package/src/components/Chart/appexChart/appexChart.html +23 -23
@@ -0,0 +1,424 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.reactnativecommunity.asyncstorage;
9
+
10
+ import android.database.Cursor;
11
+ import android.database.sqlite.SQLiteStatement;
12
+ import android.os.AsyncTask;
13
+
14
+ import com.facebook.common.logging.FLog;
15
+ import com.facebook.react.bridge.Arguments;
16
+ import com.facebook.react.bridge.Callback;
17
+ import com.facebook.react.bridge.GuardedAsyncTask;
18
+ import com.facebook.react.bridge.LifecycleEventListener;
19
+ import com.facebook.react.bridge.ReactApplicationContext;
20
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
21
+ import com.facebook.react.bridge.ReactMethod;
22
+ import com.facebook.react.bridge.ReadableArray;
23
+ import com.facebook.react.bridge.WritableArray;
24
+ import com.facebook.react.bridge.WritableMap;
25
+ import com.facebook.react.common.ReactConstants;
26
+ import com.facebook.react.common.annotations.VisibleForTesting;
27
+ import com.facebook.react.module.annotations.ReactModule;
28
+ import com.facebook.react.modules.common.ModuleDataCleaner;
29
+
30
+ import java.util.ArrayDeque;
31
+ import java.util.HashSet;
32
+ import java.util.concurrent.Executor;
33
+ import java.util.concurrent.Executors;
34
+
35
+ @ReactModule(name = AsyncStorageModule.NAME)
36
+ public final class AsyncStorageModule
37
+ extends ReactContextBaseJavaModule implements ModuleDataCleaner.Cleanable, LifecycleEventListener {
38
+
39
+ // changed name to not conflict with AsyncStorage from RN repo
40
+ public static final String NAME = "RNC_AsyncSQLiteDBStorage";
41
+
42
+ // SQL variable number limit, defined by SQLITE_LIMIT_VARIABLE_NUMBER:
43
+ // https://raw.githubusercontent.com/android/platform_external_sqlite/master/dist/sqlite3.c
44
+ private static final int MAX_SQL_KEYS = 999;
45
+
46
+ private ReactDatabaseSupplier mReactDatabaseSupplier;
47
+ private boolean mShuttingDown = false;
48
+
49
+ private final SerialExecutor executor;
50
+
51
+ public AsyncStorageModule(ReactApplicationContext reactContext) {
52
+ this(
53
+ reactContext,
54
+ BuildConfig.AsyncStorage_useDedicatedExecutor
55
+ ? Executors.newSingleThreadExecutor()
56
+ : AsyncTask.THREAD_POOL_EXECUTOR
57
+ );
58
+ }
59
+
60
+ @VisibleForTesting
61
+ AsyncStorageModule(ReactApplicationContext reactContext, Executor executor) {
62
+ super(reactContext);
63
+ // The migration MUST run before the AsyncStorage database is created for the first time.
64
+ AsyncStorageExpoMigration.migrate(reactContext);
65
+
66
+ this.executor = new SerialExecutor(executor);
67
+ reactContext.addLifecycleEventListener(this);
68
+ // Creating the database MUST happen after the migration.
69
+ mReactDatabaseSupplier = ReactDatabaseSupplier.getInstance(reactContext);
70
+ }
71
+
72
+ @Override
73
+ public String getName() {
74
+ return NAME;
75
+ }
76
+
77
+ @Override
78
+ public void initialize() {
79
+ super.initialize();
80
+ mShuttingDown = false;
81
+ }
82
+
83
+ @Override
84
+ public void onCatalystInstanceDestroy() {
85
+ mShuttingDown = true;
86
+ }
87
+
88
+ @Override
89
+ public void clearSensitiveData() {
90
+ // Clear local storage. If fails, crash, since the app is potentially in a bad state and could
91
+ // cause a privacy violation. We're still not recovering from this well, but at least the error
92
+ // will be reported to the server.
93
+ mReactDatabaseSupplier.clearAndCloseDatabase();
94
+ }
95
+
96
+ @Override
97
+ public void onHostResume() {}
98
+
99
+ @Override
100
+ public void onHostPause() {}
101
+
102
+ @Override
103
+ public void onHostDestroy() {
104
+ // ensure we close database when activity is destroyed
105
+ mReactDatabaseSupplier.closeDatabase();
106
+ }
107
+
108
+ /**
109
+ * Given an array of keys, this returns a map of (key, value) pairs for the keys found, and
110
+ * (key, null) for the keys that haven't been found.
111
+ */
112
+ @ReactMethod
113
+ public void multiGet(final ReadableArray keys, final Callback callback) {
114
+ if (keys == null) {
115
+ callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null), null);
116
+ return;
117
+ }
118
+
119
+ new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
120
+ @Override
121
+ protected void doInBackgroundGuarded(Void... params) {
122
+ if (!ensureDatabase()) {
123
+ callback.invoke(AsyncStorageErrorUtil.getDBError(null), null);
124
+ return;
125
+ }
126
+
127
+ String[] columns = {ReactDatabaseSupplier.KEY_COLUMN, ReactDatabaseSupplier.VALUE_COLUMN};
128
+ HashSet<String> keysRemaining = new HashSet<>();
129
+ WritableArray data = Arguments.createArray();
130
+ for (int keyStart = 0; keyStart < keys.size(); keyStart += MAX_SQL_KEYS) {
131
+ int keyCount = Math.min(keys.size() - keyStart, MAX_SQL_KEYS);
132
+ Cursor cursor = mReactDatabaseSupplier.get().query(
133
+ ReactDatabaseSupplier.TABLE_CATALYST,
134
+ columns,
135
+ AsyncLocalStorageUtil.buildKeySelection(keyCount),
136
+ AsyncLocalStorageUtil.buildKeySelectionArgs(keys, keyStart, keyCount),
137
+ null,
138
+ null,
139
+ null);
140
+ keysRemaining.clear();
141
+ try {
142
+ if (cursor.getCount() != keys.size()) {
143
+ // some keys have not been found - insert them with null into the final array
144
+ for (int keyIndex = keyStart; keyIndex < keyStart + keyCount; keyIndex++) {
145
+ keysRemaining.add(keys.getString(keyIndex));
146
+ }
147
+ }
148
+
149
+ if (cursor.moveToFirst()) {
150
+ do {
151
+ WritableArray row = Arguments.createArray();
152
+ row.pushString(cursor.getString(0));
153
+ row.pushString(cursor.getString(1));
154
+ data.pushArray(row);
155
+ keysRemaining.remove(cursor.getString(0));
156
+ } while (cursor.moveToNext());
157
+ }
158
+ } catch (Exception e) {
159
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
160
+ callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()), null);
161
+ return;
162
+ } finally {
163
+ cursor.close();
164
+ }
165
+
166
+ for (String key : keysRemaining) {
167
+ WritableArray row = Arguments.createArray();
168
+ row.pushString(key);
169
+ row.pushNull();
170
+ data.pushArray(row);
171
+ }
172
+ keysRemaining.clear();
173
+ }
174
+
175
+ callback.invoke(null, data);
176
+ }
177
+ }.executeOnExecutor(executor);
178
+ }
179
+
180
+ /**
181
+ * Inserts multiple (key, value) pairs. If one or more of the pairs cannot be inserted, this will
182
+ * return AsyncLocalStorageFailure, but all other pairs will have been inserted.
183
+ * The insertion will replace conflicting (key, value) pairs.
184
+ */
185
+ @ReactMethod
186
+ public void multiSet(final ReadableArray keyValueArray, final Callback callback) {
187
+ if (keyValueArray.size() == 0) {
188
+ callback.invoke();
189
+ return;
190
+ }
191
+
192
+ new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
193
+ @Override
194
+ protected void doInBackgroundGuarded(Void... params) {
195
+ if (!ensureDatabase()) {
196
+ callback.invoke(AsyncStorageErrorUtil.getDBError(null));
197
+ return;
198
+ }
199
+
200
+ String sql = "INSERT OR REPLACE INTO " + ReactDatabaseSupplier.TABLE_CATALYST + " VALUES (?, ?);";
201
+ SQLiteStatement statement = mReactDatabaseSupplier.get().compileStatement(sql);
202
+ WritableMap error = null;
203
+ try {
204
+ mReactDatabaseSupplier.get().beginTransaction();
205
+ for (int idx=0; idx < keyValueArray.size(); idx++) {
206
+ if (keyValueArray.getArray(idx).size() != 2) {
207
+ error = AsyncStorageErrorUtil.getInvalidValueError(null);
208
+ return;
209
+ }
210
+ if (keyValueArray.getArray(idx).getString(0) == null) {
211
+ error = AsyncStorageErrorUtil.getInvalidKeyError(null);
212
+ return;
213
+ }
214
+ if (keyValueArray.getArray(idx).getString(1) == null) {
215
+ error = AsyncStorageErrorUtil.getInvalidValueError(null);
216
+ return;
217
+ }
218
+
219
+ statement.clearBindings();
220
+ statement.bindString(1, keyValueArray.getArray(idx).getString(0));
221
+ statement.bindString(2, keyValueArray.getArray(idx).getString(1));
222
+ statement.execute();
223
+ }
224
+ mReactDatabaseSupplier.get().setTransactionSuccessful();
225
+ } catch (Exception e) {
226
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
227
+ error = AsyncStorageErrorUtil.getError(null, e.getMessage());
228
+ } finally {
229
+ try {
230
+ mReactDatabaseSupplier.get().endTransaction();
231
+ } catch (Exception e) {
232
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
233
+ if (error == null) {
234
+ error = AsyncStorageErrorUtil.getError(null, e.getMessage());
235
+ }
236
+ }
237
+ }
238
+ if (error != null) {
239
+ callback.invoke(error);
240
+ } else {
241
+ callback.invoke();
242
+ }
243
+ }
244
+ }.executeOnExecutor(executor);
245
+ }
246
+
247
+ /**
248
+ * Removes all rows of the keys given.
249
+ */
250
+ @ReactMethod
251
+ public void multiRemove(final ReadableArray keys, final Callback callback) {
252
+ if (keys.size() == 0) {
253
+ callback.invoke();
254
+ return;
255
+ }
256
+
257
+ new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
258
+ @Override
259
+ protected void doInBackgroundGuarded(Void... params) {
260
+ if (!ensureDatabase()) {
261
+ callback.invoke(AsyncStorageErrorUtil.getDBError(null));
262
+ return;
263
+ }
264
+
265
+ WritableMap error = null;
266
+ try {
267
+ mReactDatabaseSupplier.get().beginTransaction();
268
+ for (int keyStart = 0; keyStart < keys.size(); keyStart += MAX_SQL_KEYS) {
269
+ int keyCount = Math.min(keys.size() - keyStart, MAX_SQL_KEYS);
270
+ mReactDatabaseSupplier.get().delete(
271
+ ReactDatabaseSupplier.TABLE_CATALYST,
272
+ AsyncLocalStorageUtil.buildKeySelection(keyCount),
273
+ AsyncLocalStorageUtil.buildKeySelectionArgs(keys, keyStart, keyCount));
274
+ }
275
+ mReactDatabaseSupplier.get().setTransactionSuccessful();
276
+ } catch (Exception e) {
277
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
278
+ error = AsyncStorageErrorUtil.getError(null, e.getMessage());
279
+ } finally {
280
+ try {
281
+ mReactDatabaseSupplier.get().endTransaction();
282
+ } catch (Exception e) {
283
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
284
+ if (error == null) {
285
+ error = AsyncStorageErrorUtil.getError(null, e.getMessage());
286
+ }
287
+ }
288
+ }
289
+ if (error != null) {
290
+ callback.invoke(error);
291
+ } else {
292
+ callback.invoke();
293
+ }
294
+ }
295
+ }.executeOnExecutor(executor);
296
+ }
297
+
298
+ /**
299
+ * Given an array of (key, value) pairs, this will merge the given values with the stored values
300
+ * of the given keys, if they exist.
301
+ */
302
+ @ReactMethod
303
+ public void multiMerge(final ReadableArray keyValueArray, final Callback callback) {
304
+ new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
305
+ @Override
306
+ protected void doInBackgroundGuarded(Void... params) {
307
+ if (!ensureDatabase()) {
308
+ callback.invoke(AsyncStorageErrorUtil.getDBError(null));
309
+ return;
310
+ }
311
+ WritableMap error = null;
312
+ try {
313
+ mReactDatabaseSupplier.get().beginTransaction();
314
+ for (int idx = 0; idx < keyValueArray.size(); idx++) {
315
+ if (keyValueArray.getArray(idx).size() != 2) {
316
+ error = AsyncStorageErrorUtil.getInvalidValueError(null);
317
+ return;
318
+ }
319
+
320
+ if (keyValueArray.getArray(idx).getString(0) == null) {
321
+ error = AsyncStorageErrorUtil.getInvalidKeyError(null);
322
+ return;
323
+ }
324
+
325
+ if (keyValueArray.getArray(idx).getString(1) == null) {
326
+ error = AsyncStorageErrorUtil.getInvalidValueError(null);
327
+ return;
328
+ }
329
+
330
+ if (!AsyncLocalStorageUtil.mergeImpl(
331
+ mReactDatabaseSupplier.get(),
332
+ keyValueArray.getArray(idx).getString(0),
333
+ keyValueArray.getArray(idx).getString(1))) {
334
+ error = AsyncStorageErrorUtil.getDBError(null);
335
+ return;
336
+ }
337
+ }
338
+ mReactDatabaseSupplier.get().setTransactionSuccessful();
339
+ } catch (Exception e) {
340
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
341
+ error = AsyncStorageErrorUtil.getError(null, e.getMessage());
342
+ } finally {
343
+ try {
344
+ mReactDatabaseSupplier.get().endTransaction();
345
+ } catch (Exception e) {
346
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
347
+ if (error == null) {
348
+ error = AsyncStorageErrorUtil.getError(null, e.getMessage());
349
+ }
350
+ }
351
+ }
352
+ if (error != null) {
353
+ callback.invoke(error);
354
+ } else {
355
+ callback.invoke();
356
+ }
357
+ }
358
+ }.executeOnExecutor(executor);
359
+ }
360
+
361
+ /**
362
+ * Clears the database.
363
+ */
364
+ @ReactMethod
365
+ public void clear(final Callback callback) {
366
+ new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
367
+ @Override
368
+ protected void doInBackgroundGuarded(Void... params) {
369
+ if (!mReactDatabaseSupplier.ensureDatabase()) {
370
+ callback.invoke(AsyncStorageErrorUtil.getDBError(null));
371
+ return;
372
+ }
373
+ try {
374
+ mReactDatabaseSupplier.clear();
375
+ callback.invoke();
376
+ } catch (Exception e) {
377
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
378
+ callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()));
379
+ }
380
+ }
381
+ }.executeOnExecutor(executor);
382
+ }
383
+
384
+ /**
385
+ * Returns an array with all keys from the database.
386
+ */
387
+ @ReactMethod
388
+ public void getAllKeys(final Callback callback) {
389
+ new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
390
+ @Override
391
+ protected void doInBackgroundGuarded(Void... params) {
392
+ if (!ensureDatabase()) {
393
+ callback.invoke(AsyncStorageErrorUtil.getDBError(null), null);
394
+ return;
395
+ }
396
+ WritableArray data = Arguments.createArray();
397
+ String[] columns = {ReactDatabaseSupplier.KEY_COLUMN};
398
+ Cursor cursor = mReactDatabaseSupplier.get()
399
+ .query(ReactDatabaseSupplier.TABLE_CATALYST, columns, null, null, null, null, null);
400
+ try {
401
+ if (cursor.moveToFirst()) {
402
+ do {
403
+ data.pushString(cursor.getString(0));
404
+ } while (cursor.moveToNext());
405
+ }
406
+ } catch (Exception e) {
407
+ FLog.w(ReactConstants.TAG, e.getMessage(), e);
408
+ callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()), null);
409
+ return;
410
+ } finally {
411
+ cursor.close();
412
+ }
413
+ callback.invoke(null, data);
414
+ }
415
+ }.executeOnExecutor(executor);
416
+ }
417
+
418
+ /**
419
+ * Verify the database is open for reads and writes.
420
+ */
421
+ private boolean ensureDatabase() {
422
+ return !mShuttingDown && mReactDatabaseSupplier.ensureDatabase();
423
+ }
424
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.reactnativecommunity.asyncstorage;
9
+
10
+ import android.util.Log;
11
+ import com.facebook.react.ReactPackage;
12
+ import com.facebook.react.bridge.JavaScriptModule;
13
+ import com.facebook.react.bridge.NativeModule;
14
+ import com.facebook.react.bridge.ReactApplicationContext;
15
+ import com.facebook.react.bridge.ReactContext;
16
+ import com.facebook.react.uimanager.ViewManager;
17
+ import java.util.ArrayList;
18
+ import java.util.Collections;
19
+ import java.util.List;
20
+
21
+ public class AsyncStoragePackage implements ReactPackage {
22
+ @Override
23
+ public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
24
+
25
+ List<NativeModule> moduleList = new ArrayList<>(1);
26
+
27
+ if (BuildConfig.AsyncStorage_useNextStorage) {
28
+ try {
29
+ Class storageClass = Class.forName("com.reactnativecommunity.asyncstorage.next.StorageModule");
30
+ NativeModule inst = (NativeModule) storageClass.getDeclaredConstructor(new Class[]{ReactContext.class}).newInstance(reactContext);
31
+ moduleList.add(inst);
32
+ AsyncLocalStorageUtil.verifyAndForceSqliteCheckpoint(reactContext);
33
+ } catch (Exception e) {
34
+ String message = "Something went wrong when initializing module:"
35
+ + "\n"
36
+ + e.getCause().getClass()
37
+ + "\n"
38
+ + "Cause:" + e.getCause().getLocalizedMessage();
39
+ Log.e("AsyncStorage_Next", message);
40
+ }
41
+ } else {
42
+ moduleList.add(new AsyncStorageModule(reactContext));
43
+ }
44
+
45
+ return moduleList;
46
+ }
47
+
48
+ // Deprecated in RN 0.47
49
+ public List<Class<? extends JavaScriptModule>> createJSModules() {
50
+ return Collections.emptyList();
51
+ }
52
+
53
+ @Override
54
+ @SuppressWarnings("rawtypes")
55
+ public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
56
+ return Collections.emptyList();
57
+ }
58
+ }
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ package com.reactnativecommunity.asyncstorage;
9
+
10
+ import android.content.Context;
11
+ import android.database.sqlite.SQLiteDatabase;
12
+ import android.database.sqlite.SQLiteException;
13
+ import android.database.sqlite.SQLiteOpenHelper;
14
+ import com.facebook.common.logging.FLog;
15
+ import com.facebook.react.common.ReactConstants;
16
+ import javax.annotation.Nullable;
17
+
18
+ /**
19
+ * Database supplier of the database used by react native. This creates, opens and deletes the
20
+ * database as necessary.
21
+ */
22
+ public class ReactDatabaseSupplier extends SQLiteOpenHelper {
23
+
24
+ // VisibleForTesting
25
+ public static final String DATABASE_NAME = "RKStorage";
26
+
27
+ private static final int DATABASE_VERSION = 1;
28
+ private static final int SLEEP_TIME_MS = 30;
29
+
30
+ static final String TABLE_CATALYST = "catalystLocalStorage";
31
+ static final String KEY_COLUMN = "key";
32
+ static final String VALUE_COLUMN = "value";
33
+
34
+ static final String VERSION_TABLE_CREATE =
35
+ "CREATE TABLE " + TABLE_CATALYST + " (" +
36
+ KEY_COLUMN + " TEXT PRIMARY KEY, " +
37
+ VALUE_COLUMN + " TEXT NOT NULL" +
38
+ ")";
39
+
40
+ private static @Nullable ReactDatabaseSupplier sReactDatabaseSupplierInstance;
41
+
42
+ private Context mContext;
43
+ private @Nullable SQLiteDatabase mDb;
44
+ private long mMaximumDatabaseSize = BuildConfig.AsyncStorage_db_size * 1024L * 1024L;
45
+
46
+ private ReactDatabaseSupplier(Context context) {
47
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
48
+ mContext = context;
49
+ }
50
+
51
+ public static ReactDatabaseSupplier getInstance(Context context) {
52
+ if (sReactDatabaseSupplierInstance == null) {
53
+ sReactDatabaseSupplierInstance = new ReactDatabaseSupplier(context.getApplicationContext());
54
+ }
55
+ return sReactDatabaseSupplierInstance;
56
+ }
57
+
58
+ @Override
59
+ public void onCreate(SQLiteDatabase db) {
60
+ db.execSQL(VERSION_TABLE_CREATE);
61
+ }
62
+
63
+ @Override
64
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
65
+ if (oldVersion != newVersion) {
66
+ deleteDatabase();
67
+ onCreate(db);
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Verify the database exists and is open.
73
+ */
74
+ /* package */ synchronized boolean ensureDatabase() {
75
+ if (mDb != null && mDb.isOpen()) {
76
+ return true;
77
+ }
78
+ // Sometimes retrieving the database fails. We do 2 retries: first without database deletion
79
+ // and then with deletion.
80
+ SQLiteException lastSQLiteException = null;
81
+ for (int tries = 0; tries < 2; tries++) {
82
+ try {
83
+ if (tries > 0) {
84
+ deleteDatabase();
85
+ }
86
+ mDb = getWritableDatabase();
87
+ break;
88
+ } catch (SQLiteException e) {
89
+ lastSQLiteException = e;
90
+ }
91
+ // Wait before retrying.
92
+ try {
93
+ Thread.sleep(SLEEP_TIME_MS);
94
+ } catch (InterruptedException ie) {
95
+ Thread.currentThread().interrupt();
96
+ }
97
+ }
98
+ if (mDb == null) {
99
+ throw lastSQLiteException;
100
+ }
101
+ // This is a sane limit to protect the user from the app storing too much data in the database.
102
+ // This also protects the database from filling up the disk cache and becoming malformed
103
+ // (endTransaction() calls will throw an exception, not rollback, and leave the db malformed).
104
+ mDb.setMaximumSize(mMaximumDatabaseSize);
105
+ return true;
106
+ }
107
+
108
+ /**
109
+ * Create and/or open the database.
110
+ */
111
+ public synchronized SQLiteDatabase get() {
112
+ ensureDatabase();
113
+ return mDb;
114
+ }
115
+
116
+ public synchronized void clearAndCloseDatabase() throws RuntimeException {
117
+ try {
118
+ clear();
119
+ closeDatabase();
120
+ FLog.d(ReactConstants.TAG, "Cleaned " + DATABASE_NAME);
121
+ } catch (Exception e) {
122
+ // Clearing the database has failed, delete it instead.
123
+ if (deleteDatabase()) {
124
+ FLog.d(ReactConstants.TAG, "Deleted Local Database " + DATABASE_NAME);
125
+ return;
126
+ }
127
+ // Everything failed, throw
128
+ throw new RuntimeException("Clearing and deleting database " + DATABASE_NAME + " failed");
129
+ }
130
+ }
131
+
132
+ /* package */ synchronized void clear() {
133
+ get().delete(TABLE_CATALYST, null, null);
134
+ }
135
+
136
+ /**
137
+ * Sets the maximum size the database will grow to. The maximum size cannot
138
+ * be set below the current size.
139
+ */
140
+ public synchronized void setMaximumSize(long size) {
141
+ mMaximumDatabaseSize = size;
142
+ if (mDb != null) {
143
+ mDb.setMaximumSize(mMaximumDatabaseSize);
144
+ }
145
+ }
146
+
147
+ private synchronized boolean deleteDatabase() {
148
+ closeDatabase();
149
+ return mContext.deleteDatabase(DATABASE_NAME);
150
+ }
151
+
152
+ public synchronized void closeDatabase() {
153
+ if (mDb != null && mDb.isOpen()) {
154
+ mDb.close();
155
+ mDb = null;
156
+ }
157
+ }
158
+
159
+ // For testing purposes only!
160
+ public static void deleteInstance() {
161
+ sReactDatabaseSupplierInstance = null;
162
+ }
163
+ }
@@ -0,0 +1,40 @@
1
+ package com.reactnativecommunity.asyncstorage;
2
+
3
+ import java.util.ArrayDeque;
4
+ import java.util.concurrent.Executor;
5
+
6
+ /**
7
+ * Detox is using this implementation detail in its environment setup,
8
+ * so in order for Next storage to work, this class has been made public
9
+ *
10
+ * Adapted from https://android.googlesource.com/platform/frameworks/base.git/+/1488a3a19d4681a41fb45570c15e14d99db1cb66/core/java/android/os/AsyncTask.java#237
11
+ */
12
+ public class SerialExecutor implements Executor {
13
+ private final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
14
+ private Runnable mActive;
15
+ private final Executor executor;
16
+
17
+ public SerialExecutor(Executor executor) {
18
+ this.executor = executor;
19
+ }
20
+
21
+ public synchronized void execute(final Runnable r) {
22
+ mTasks.offer(new Runnable() {
23
+ public void run() {
24
+ try {
25
+ r.run();
26
+ } finally {
27
+ scheduleNext();
28
+ }
29
+ }
30
+ });
31
+ if (mActive == null) {
32
+ scheduleNext();
33
+ }
34
+ }
35
+ synchronized void scheduleNext() {
36
+ if ((mActive = mTasks.poll()) != null) {
37
+ executor.execute(mActive);
38
+ }
39
+ }
40
+ }