react-native-mmkv 2.3.3 → 2.4.2

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 CHANGED
@@ -52,11 +52,15 @@ react-native-mmkv is sponsored by **getstream.io**. <br/>
52
52
 
53
53
  ## Benchmark
54
54
 
55
+ [StorageBenchmark](https://github.com/mrousavy/StorageBenchmark) compares popular storage libraries against each other by reading a value from storage for 1000 times:
56
+
55
57
  <div align="center">
56
- <img src="./img/benchmark_1000_get.png" />
58
+ <a href="https://github.com/mrousavy/StorageBenchmark">
59
+ <img src="./img/benchmark_1000_get.png" />
60
+ </a>
57
61
  <p>
58
- <b>AsyncStorage vs MMKV</b>: Reading a value from Storage 1000 times. <br/>
59
- Measured in milliseconds on an iPhone 8, lower is better.
62
+ <b>MMKV vs other storage libraries</b>: Reading a value from Storage 1000 times. <br/>
63
+ Measured in milliseconds on an iPhone 11 Pro, lower is better. <br/>
60
64
  </p>
61
65
  </div>
62
66
 
@@ -170,6 +174,10 @@ storage.recrypt('hunter2')
170
174
  storage.recrypt(undefined)
171
175
  ```
172
176
 
177
+ ## Testing with Jest
178
+
179
+ A mocked MMKV instance is automatically used when testing with Jest, so you will be able to use `new MMKV()` as per normal in your tests. Refer to [example/test/MMKV.test.ts](example/test/MMKV.test.ts) for an example.
180
+
173
181
  ## Documentation
174
182
 
175
183
  * [Hooks](./docs/HOOKS.md)
@@ -179,6 +187,7 @@ storage.recrypt(undefined)
179
187
  * [Using MMKV with mobx-persist-storage](./docs/WRAPPER_MOBX.md)
180
188
  * [Using MMKV with mobx-persist](./docs/WRAPPER_MOBXPERSIST.md)
181
189
  * [Using MMKV with zustand persist-middleware](./docs/WRAPPER_ZUSTAND_PERSIST_MIDDLEWARE.md)
190
+ * [Using MMKV with jotai](./docs/WRAPPER_JOTAI.md)
182
191
  * [How is this library different from **react-native-mmkv-storage**?](https://github.com/mrousavy/react-native-mmkv/issues/100#issuecomment-886477361)
183
192
 
184
193
  ## Limitations
@@ -160,7 +160,17 @@ dependencies {
160
160
  extractJNI("com.facebook.fbjni:fbjni:+")
161
161
 
162
162
  if (!sourceBuild) {
163
- def rnAAR = fileTree("${defaultDir.toString()}").matching({ it.include "**/**/*.aar" }).singleFile
163
+ def buildType = "debug"
164
+ tasks.all({ task ->
165
+ if (task.name == "buildCMakeRelease") {
166
+ buildType = "release"
167
+ }
168
+ })
169
+ def rnAarMatcher = "**/react-native/**/*${buildType}.aar"
170
+ if (REACT_NATIVE_VERSION < 69) {
171
+ rnAarMatcher = "**/**/*.aar"
172
+ }
173
+ def rnAAR = fileTree("${defaultDir.toString()}").matching({ it.include rnAarMatcher }).singleFile
164
174
  extractJNI(files(rnAAR))
165
175
  }
166
176
  }
@@ -193,7 +203,12 @@ task createNativeDepsDirectories {
193
203
  }
194
204
 
195
205
  task downloadBoost(dependsOn: createNativeDepsDirectories, type: Download) {
196
- src("https://github.com/react-native-community/boost-for-react-native/releases/download/v${BOOST_VERSION.replace("_", ".")}-0/boost_${BOOST_VERSION}.tar.gz")
206
+ def transformedVersion = BOOST_VERSION.replace("_", ".")
207
+ def srcUrl = "https://boostorg.jfrog.io/artifactory/main/release/${transformedVersion}/source/boost_${BOOST_VERSION}.tar.gz"
208
+ if (REACT_NATIVE_VERSION < 69) {
209
+ srcUrl = "https://github.com/react-native-community/boost-for-react-native/releases/download/v${transformedVersion}-0/boost_${BOOST_VERSION}.tar.gz"
210
+ }
211
+ src(srcUrl)
197
212
  onlyIfNewer(true)
198
213
  overwrite(false)
199
214
  dest(boost_file)
@@ -232,7 +232,7 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
232
232
  size_t count) -> jsi::Value {
233
233
  if (arguments[0].isUndefined()) {
234
234
  // reset encryption key to "no encryption"
235
- instance->reKey(nullptr);
235
+ instance->reKey(std::string());
236
236
  } else if (arguments[0].isString()) {
237
237
  // reKey(..) with new encryption-key
238
238
  auto encryptionKey = arguments[0].getString(runtime).utf8(runtime);
@@ -7,6 +7,10 @@ exports.MMKV = void 0;
7
7
 
8
8
  var _createMMKV = require("./createMMKV");
9
9
 
10
+ var _createMMKV2 = require("./createMMKV.mock");
11
+
12
+ var _PlatformChecker = require("./PlatformChecker");
13
+
10
14
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
15
 
12
16
  const onValueChangedListeners = new Map();
@@ -29,7 +33,7 @@ class MMKV {
29
33
  _defineProperty(this, "id", void 0);
30
34
 
31
35
  this.id = configuration.id;
32
- this.nativeInstance = (0, _createMMKV.createMMKV)(configuration);
36
+ this.nativeInstance = (0, _PlatformChecker.isJest)() ? (0, _createMMKV2.createMockMMKV)() : (0, _createMMKV.createMMKV)(configuration);
33
37
  this.functionCache = {};
34
38
  }
35
39
 
@@ -1 +1 @@
1
- {"version":3,"sources":["MMKV.ts"],"names":["onValueChangedListeners","Map","MMKV","constructor","configuration","id","nativeInstance","functionCache","has","set","get","getFunctionFromCache","functionName","onValuesChanged","keys","length","key","listener","value","func","getBoolean","getString","getNumber","contains","delete","getAllKeys","clearAll","recrypt","toString","join","toJSON","addOnValueChangedListener","onValueChanged","push","remove","index","indexOf","splice"],"mappings":"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","sourcesContent":["import { createMMKV } from './createMMKV';\n\ninterface Listener {\n remove: () => void;\n}\n\n/**\n * Used for configuration of a single MMKV instance.\n */\nexport interface MMKVConfiguration {\n /**\n * The MMKV instance's ID. If you want to use multiple instances, make sure to use different IDs!\n *\n * @example\n * ```ts\n * const userStorage = new MMKV({ id: `user-${userId}-storage` })\n * const globalStorage = new MMKV({ id: 'global-app-storage' })\n * ```\n *\n * @default 'mmkv.default'\n */\n id: string;\n /**\n * The MMKV instance's root path. By default, MMKV stores file inside `$(Documents)/mmkv/`. You can customize MMKV's root directory on MMKV initialization:\n *\n * @example\n * ```ts\n * const temporaryStorage = new MMKV({ path: '/tmp/' })\n * ```\n */\n path?: string;\n /**\n * The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV.\n *\n * Encryption keys can have a maximum length of 16 bytes.\n *\n * @example\n * ```ts\n * const secureStorage = new MMKV({ encryptionKey: 'my-encryption-key!' })\n * ```\n */\n encryptionKey?: string;\n}\n\n/**\n * Represents a single MMKV instance.\n */\ninterface MMKVInterface {\n /**\n * Set a value for the given `key`.\n */\n set: (key: string, value: boolean | string | number) => void;\n /**\n * Get the boolean value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getBoolean: (key: string) => boolean | undefined;\n /**\n * Get the string value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getString: (key: string) => string | undefined;\n /**\n * Get the number value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getNumber: (key: string) => number | undefined;\n /**\n * Checks whether the given `key` is being stored in this MMKV instance.\n */\n contains: (key: string) => boolean;\n /**\n * Delete the given `key`.\n */\n delete: (key: string) => void;\n /**\n * Get all keys.\n *\n * @default []\n */\n getAllKeys: () => string[];\n /**\n * Delete all keys.\n */\n clearAll: () => void;\n /**\n * Sets (or updates) the encryption-key to encrypt all data in this MMKV instance with.\n *\n * To remove encryption, pass `undefined` as a key.\n *\n * Encryption keys can have a maximum length of 16 bytes.\n */\n recrypt: (key: string | undefined) => void;\n /**\n * Adds a value changed listener. The Listener will be called whenever any value\n * in this storage instance changes (set or delete).\n *\n * To unsubscribe from value changes, call `remove()` on the Listener.\n */\n addOnValueChangedListener: (\n onValueChanged: (key: string) => void\n ) => Listener;\n}\n\nexport type NativeMMKV = Pick<\n MMKVInterface,\n | 'clearAll'\n | 'contains'\n | 'delete'\n | 'getAllKeys'\n | 'getBoolean'\n | 'getNumber'\n | 'getString'\n | 'set'\n | 'recrypt'\n>;\n\nconst onValueChangedListeners = new Map<string, ((key: string) => void)[]>();\n\n/**\n * A single MMKV instance.\n */\nexport class MMKV implements MMKVInterface {\n private nativeInstance: NativeMMKV;\n private functionCache: Partial<NativeMMKV>;\n private id: string;\n\n /**\n * Creates a new MMKV instance with the given Configuration.\n * If no custom `id` is supplied, `'mmkv.default'` will be used.\n */\n constructor(configuration: MMKVConfiguration = { id: 'mmkv.default' }) {\n this.id = configuration.id;\n this.nativeInstance = createMMKV(configuration);\n this.functionCache = {};\n }\n\n private get onValueChangedListeners() {\n if (!onValueChangedListeners.has(this.id)) {\n onValueChangedListeners.set(this.id, []);\n }\n return onValueChangedListeners.get(this.id)!;\n }\n\n private getFunctionFromCache<T extends keyof NativeMMKV>(\n functionName: T\n ): NativeMMKV[T] {\n if (this.functionCache[functionName] == null) {\n this.functionCache[functionName] = this.nativeInstance[functionName];\n }\n return this.functionCache[functionName] as NativeMMKV[T];\n }\n\n private onValuesChanged(keys: string[]) {\n if (this.onValueChangedListeners.length === 0) return;\n\n for (const key of keys) {\n for (const listener of this.onValueChangedListeners) {\n listener(key);\n }\n }\n }\n\n set(key: string, value: boolean | string | number): void {\n const func = this.getFunctionFromCache('set');\n func(key, value);\n\n this.onValuesChanged([key]);\n }\n getBoolean(key: string): boolean | undefined {\n const func = this.getFunctionFromCache('getBoolean');\n return func(key);\n }\n getString(key: string): string | undefined {\n const func = this.getFunctionFromCache('getString');\n return func(key);\n }\n getNumber(key: string): number | undefined {\n const func = this.getFunctionFromCache('getNumber');\n return func(key);\n }\n contains(key: string): boolean {\n const func = this.getFunctionFromCache('contains');\n return func(key);\n }\n delete(key: string): void {\n const func = this.getFunctionFromCache('delete');\n func(key);\n\n this.onValuesChanged([key]);\n }\n getAllKeys(): string[] {\n const func = this.getFunctionFromCache('getAllKeys');\n return func();\n }\n clearAll(): void {\n const keys = this.getAllKeys();\n\n const func = this.getFunctionFromCache('clearAll');\n func();\n\n this.onValuesChanged(keys);\n }\n recrypt(key: string | undefined): void {\n const func = this.getFunctionFromCache('recrypt');\n return func(key);\n }\n\n toString(): string {\n return `MMKV (${this.id}): [${this.getAllKeys().join(', ')}]`;\n }\n toJSON(): object {\n return {\n [this.id]: this.getAllKeys(),\n };\n }\n\n addOnValueChangedListener(onValueChanged: (key: string) => void): Listener {\n this.onValueChangedListeners.push(onValueChanged);\n\n return {\n remove: () => {\n const index = this.onValueChangedListeners.indexOf(onValueChanged);\n if (index !== -1) {\n this.onValueChangedListeners.splice(index, 1);\n }\n },\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["MMKV.ts"],"names":["onValueChangedListeners","Map","MMKV","constructor","configuration","id","nativeInstance","functionCache","has","set","get","getFunctionFromCache","functionName","onValuesChanged","keys","length","key","listener","value","func","getBoolean","getString","getNumber","contains","delete","getAllKeys","clearAll","recrypt","toString","join","toJSON","addOnValueChangedListener","onValueChanged","push","remove","index","indexOf","splice"],"mappings":"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","sourcesContent":["import { createMMKV } from './createMMKV';\nimport { createMockMMKV } from './createMMKV.mock';\nimport { isJest } from './PlatformChecker';\n\ninterface Listener {\n remove: () => void;\n}\n\n/**\n * Used for configuration of a single MMKV instance.\n */\nexport interface MMKVConfiguration {\n /**\n * The MMKV instance's ID. If you want to use multiple instances, make sure to use different IDs!\n *\n * @example\n * ```ts\n * const userStorage = new MMKV({ id: `user-${userId}-storage` })\n * const globalStorage = new MMKV({ id: 'global-app-storage' })\n * ```\n *\n * @default 'mmkv.default'\n */\n id: string;\n /**\n * The MMKV instance's root path. By default, MMKV stores file inside `$(Documents)/mmkv/`. You can customize MMKV's root directory on MMKV initialization:\n *\n * @example\n * ```ts\n * const temporaryStorage = new MMKV({ path: '/tmp/' })\n * ```\n */\n path?: string;\n /**\n * The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV.\n *\n * Encryption keys can have a maximum length of 16 bytes.\n *\n * @example\n * ```ts\n * const secureStorage = new MMKV({ encryptionKey: 'my-encryption-key!' })\n * ```\n */\n encryptionKey?: string;\n}\n\n/**\n * Represents a single MMKV instance.\n */\ninterface MMKVInterface {\n /**\n * Set a value for the given `key`.\n */\n set: (key: string, value: boolean | string | number) => void;\n /**\n * Get the boolean value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getBoolean: (key: string) => boolean | undefined;\n /**\n * Get the string value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getString: (key: string) => string | undefined;\n /**\n * Get the number value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getNumber: (key: string) => number | undefined;\n /**\n * Checks whether the given `key` is being stored in this MMKV instance.\n */\n contains: (key: string) => boolean;\n /**\n * Delete the given `key`.\n */\n delete: (key: string) => void;\n /**\n * Get all keys.\n *\n * @default []\n */\n getAllKeys: () => string[];\n /**\n * Delete all keys.\n */\n clearAll: () => void;\n /**\n * Sets (or updates) the encryption-key to encrypt all data in this MMKV instance with.\n *\n * To remove encryption, pass `undefined` as a key.\n *\n * Encryption keys can have a maximum length of 16 bytes.\n */\n recrypt: (key: string | undefined) => void;\n /**\n * Adds a value changed listener. The Listener will be called whenever any value\n * in this storage instance changes (set or delete).\n *\n * To unsubscribe from value changes, call `remove()` on the Listener.\n */\n addOnValueChangedListener: (\n onValueChanged: (key: string) => void\n ) => Listener;\n}\n\nexport type NativeMMKV = Pick<\n MMKVInterface,\n | 'clearAll'\n | 'contains'\n | 'delete'\n | 'getAllKeys'\n | 'getBoolean'\n | 'getNumber'\n | 'getString'\n | 'set'\n | 'recrypt'\n>;\n\nconst onValueChangedListeners = new Map<string, ((key: string) => void)[]>();\n\n/**\n * A single MMKV instance.\n */\nexport class MMKV implements MMKVInterface {\n private nativeInstance: NativeMMKV;\n private functionCache: Partial<NativeMMKV>;\n private id: string;\n\n /**\n * Creates a new MMKV instance with the given Configuration.\n * If no custom `id` is supplied, `'mmkv.default'` will be used.\n */\n constructor(configuration: MMKVConfiguration = { id: 'mmkv.default' }) {\n this.id = configuration.id;\n this.nativeInstance = isJest()\n ? createMockMMKV()\n : createMMKV(configuration);\n this.functionCache = {};\n }\n\n private get onValueChangedListeners() {\n if (!onValueChangedListeners.has(this.id)) {\n onValueChangedListeners.set(this.id, []);\n }\n return onValueChangedListeners.get(this.id)!;\n }\n\n private getFunctionFromCache<T extends keyof NativeMMKV>(\n functionName: T\n ): NativeMMKV[T] {\n if (this.functionCache[functionName] == null) {\n this.functionCache[functionName] = this.nativeInstance[functionName];\n }\n return this.functionCache[functionName] as NativeMMKV[T];\n }\n\n private onValuesChanged(keys: string[]) {\n if (this.onValueChangedListeners.length === 0) return;\n\n for (const key of keys) {\n for (const listener of this.onValueChangedListeners) {\n listener(key);\n }\n }\n }\n\n set(key: string, value: boolean | string | number): void {\n const func = this.getFunctionFromCache('set');\n func(key, value);\n\n this.onValuesChanged([key]);\n }\n getBoolean(key: string): boolean | undefined {\n const func = this.getFunctionFromCache('getBoolean');\n return func(key);\n }\n getString(key: string): string | undefined {\n const func = this.getFunctionFromCache('getString');\n return func(key);\n }\n getNumber(key: string): number | undefined {\n const func = this.getFunctionFromCache('getNumber');\n return func(key);\n }\n contains(key: string): boolean {\n const func = this.getFunctionFromCache('contains');\n return func(key);\n }\n delete(key: string): void {\n const func = this.getFunctionFromCache('delete');\n func(key);\n\n this.onValuesChanged([key]);\n }\n getAllKeys(): string[] {\n const func = this.getFunctionFromCache('getAllKeys');\n return func();\n }\n clearAll(): void {\n const keys = this.getAllKeys();\n\n const func = this.getFunctionFromCache('clearAll');\n func();\n\n this.onValuesChanged(keys);\n }\n recrypt(key: string | undefined): void {\n const func = this.getFunctionFromCache('recrypt');\n return func(key);\n }\n\n toString(): string {\n return `MMKV (${this.id}): [${this.getAllKeys().join(', ')}]`;\n }\n toJSON(): object {\n return {\n [this.id]: this.getAllKeys(),\n };\n }\n\n addOnValueChangedListener(onValueChanged: (key: string) => void): Listener {\n this.onValueChangedListeners.push(onValueChanged);\n\n return {\n remove: () => {\n const index = this.onValueChangedListeners.indexOf(onValueChanged);\n if (index !== -1) {\n this.onValueChangedListeners.splice(index, 1);\n }\n },\n };\n }\n}\n"]}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isJest = isJest;
7
+
8
+ function isJest() {
9
+ return process.env.JEST_WORKER_ID != null;
10
+ }
11
+ //# sourceMappingURL=PlatformChecker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["PlatformChecker.ts"],"names":["isJest","process","env","JEST_WORKER_ID"],"mappings":";;;;;;;AAAO,SAASA,MAAT,GAA2B;AAChC,SAAOC,OAAO,CAACC,GAAR,CAAYC,cAAZ,IAA8B,IAArC;AACD","sourcesContent":["export function isJest(): boolean {\n return process.env.JEST_WORKER_ID != null;\n}\n"]}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createMockMMKV = void 0;
7
+
8
+ /* Mock MMKV instance for use in tests */
9
+ const createMockMMKV = () => {
10
+ const storage = new Map();
11
+ return {
12
+ clearAll: () => storage.clear(),
13
+ delete: key => storage.delete(key),
14
+ set: (key, value) => storage.set(key, value),
15
+ getString: key => {
16
+ const result = storage.get(key);
17
+ return typeof result === 'string' ? result : undefined;
18
+ },
19
+ getNumber: key => {
20
+ const result = storage.get(key);
21
+ return typeof result === 'number' ? result : undefined;
22
+ },
23
+ getBoolean: key => {
24
+ const result = storage.get(key);
25
+ return typeof result === 'boolean' ? result : undefined;
26
+ },
27
+ getAllKeys: () => Array.from(storage.keys()),
28
+ contains: key => storage.has(key),
29
+ recrypt: () => {
30
+ console.warn('Encryption is not supported in mocked MMKV instances!');
31
+ }
32
+ };
33
+ };
34
+
35
+ exports.createMockMMKV = createMockMMKV;
36
+ //# sourceMappingURL=createMMKV.mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["createMMKV.mock.ts"],"names":["createMockMMKV","storage","Map","clearAll","clear","delete","key","set","value","getString","result","get","undefined","getNumber","getBoolean","getAllKeys","Array","from","keys","contains","has","recrypt","console","warn"],"mappings":";;;;;;;AAEA;AACO,MAAMA,cAAc,GAAG,MAAkB;AAC9C,QAAMC,OAAO,GAAG,IAAIC,GAAJ,EAAhB;AAEA,SAAO;AACLC,IAAAA,QAAQ,EAAE,MAAMF,OAAO,CAACG,KAAR,EADX;AAELC,IAAAA,MAAM,EAAGC,GAAD,IAASL,OAAO,CAACI,MAAR,CAAeC,GAAf,CAFZ;AAGLC,IAAAA,GAAG,EAAE,CAACD,GAAD,EAAME,KAAN,KAAgBP,OAAO,CAACM,GAAR,CAAYD,GAAZ,EAAiBE,KAAjB,CAHhB;AAILC,IAAAA,SAAS,EAAGH,GAAD,IAAS;AAClB,YAAMI,MAAM,GAAGT,OAAO,CAACU,GAAR,CAAYL,GAAZ,CAAf;AACA,aAAO,OAAOI,MAAP,KAAkB,QAAlB,GAA6BA,MAA7B,GAAsCE,SAA7C;AACD,KAPI;AAQLC,IAAAA,SAAS,EAAGP,GAAD,IAAS;AAClB,YAAMI,MAAM,GAAGT,OAAO,CAACU,GAAR,CAAYL,GAAZ,CAAf;AACA,aAAO,OAAOI,MAAP,KAAkB,QAAlB,GAA6BA,MAA7B,GAAsCE,SAA7C;AACD,KAXI;AAYLE,IAAAA,UAAU,EAAGR,GAAD,IAAS;AACnB,YAAMI,MAAM,GAAGT,OAAO,CAACU,GAAR,CAAYL,GAAZ,CAAf;AACA,aAAO,OAAOI,MAAP,KAAkB,SAAlB,GAA8BA,MAA9B,GAAuCE,SAA9C;AACD,KAfI;AAgBLG,IAAAA,UAAU,EAAE,MAAMC,KAAK,CAACC,IAAN,CAAWhB,OAAO,CAACiB,IAAR,EAAX,CAhBb;AAiBLC,IAAAA,QAAQ,EAAGb,GAAD,IAASL,OAAO,CAACmB,GAAR,CAAYd,GAAZ,CAjBd;AAkBLe,IAAAA,OAAO,EAAE,MAAM;AACbC,MAAAA,OAAO,CAACC,IAAR,CAAa,uDAAb;AACD;AApBI,GAAP;AAsBD,CAzBM","sourcesContent":["import type { NativeMMKV } from 'react-native-mmkv';\n\n/* Mock MMKV instance for use in tests */\nexport const createMockMMKV = (): NativeMMKV => {\n const storage = new Map<string, string | boolean | number>();\n\n return {\n clearAll: () => storage.clear(),\n delete: (key) => storage.delete(key),\n set: (key, value) => storage.set(key, value),\n getString: (key) => {\n const result = storage.get(key);\n return typeof result === 'string' ? result : undefined;\n },\n getNumber: (key) => {\n const result = storage.get(key);\n return typeof result === 'number' ? result : undefined;\n },\n getBoolean: (key) => {\n const result = storage.get(key);\n return typeof result === 'boolean' ? result : undefined;\n },\n getAllKeys: () => Array.from(storage.keys()),\n contains: (key) => storage.has(key),\n recrypt: () => {\n console.warn('Encryption is not supported in mocked MMKV instances!');\n },\n };\n};\n"]}
@@ -1,6 +1,8 @@
1
1
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
2
 
3
3
  import { createMMKV } from './createMMKV';
4
+ import { createMockMMKV } from './createMMKV.mock';
5
+ import { isJest } from './PlatformChecker';
4
6
  const onValueChangedListeners = new Map();
5
7
  /**
6
8
  * A single MMKV instance.
@@ -21,7 +23,7 @@ export class MMKV {
21
23
  _defineProperty(this, "id", void 0);
22
24
 
23
25
  this.id = configuration.id;
24
- this.nativeInstance = createMMKV(configuration);
26
+ this.nativeInstance = isJest() ? createMockMMKV() : createMMKV(configuration);
25
27
  this.functionCache = {};
26
28
  }
27
29
 
@@ -1 +1 @@
1
- {"version":3,"sources":["MMKV.ts"],"names":["createMMKV","onValueChangedListeners","Map","MMKV","constructor","configuration","id","nativeInstance","functionCache","has","set","get","getFunctionFromCache","functionName","onValuesChanged","keys","length","key","listener","value","func","getBoolean","getString","getNumber","contains","delete","getAllKeys","clearAll","recrypt","toString","join","toJSON","addOnValueChangedListener","onValueChanged","push","remove","index","indexOf","splice"],"mappings":"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","sourcesContent":["import { createMMKV } from './createMMKV';\n\ninterface Listener {\n remove: () => void;\n}\n\n/**\n * Used for configuration of a single MMKV instance.\n */\nexport interface MMKVConfiguration {\n /**\n * The MMKV instance's ID. If you want to use multiple instances, make sure to use different IDs!\n *\n * @example\n * ```ts\n * const userStorage = new MMKV({ id: `user-${userId}-storage` })\n * const globalStorage = new MMKV({ id: 'global-app-storage' })\n * ```\n *\n * @default 'mmkv.default'\n */\n id: string;\n /**\n * The MMKV instance's root path. By default, MMKV stores file inside `$(Documents)/mmkv/`. You can customize MMKV's root directory on MMKV initialization:\n *\n * @example\n * ```ts\n * const temporaryStorage = new MMKV({ path: '/tmp/' })\n * ```\n */\n path?: string;\n /**\n * The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV.\n *\n * Encryption keys can have a maximum length of 16 bytes.\n *\n * @example\n * ```ts\n * const secureStorage = new MMKV({ encryptionKey: 'my-encryption-key!' })\n * ```\n */\n encryptionKey?: string;\n}\n\n/**\n * Represents a single MMKV instance.\n */\ninterface MMKVInterface {\n /**\n * Set a value for the given `key`.\n */\n set: (key: string, value: boolean | string | number) => void;\n /**\n * Get the boolean value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getBoolean: (key: string) => boolean | undefined;\n /**\n * Get the string value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getString: (key: string) => string | undefined;\n /**\n * Get the number value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getNumber: (key: string) => number | undefined;\n /**\n * Checks whether the given `key` is being stored in this MMKV instance.\n */\n contains: (key: string) => boolean;\n /**\n * Delete the given `key`.\n */\n delete: (key: string) => void;\n /**\n * Get all keys.\n *\n * @default []\n */\n getAllKeys: () => string[];\n /**\n * Delete all keys.\n */\n clearAll: () => void;\n /**\n * Sets (or updates) the encryption-key to encrypt all data in this MMKV instance with.\n *\n * To remove encryption, pass `undefined` as a key.\n *\n * Encryption keys can have a maximum length of 16 bytes.\n */\n recrypt: (key: string | undefined) => void;\n /**\n * Adds a value changed listener. The Listener will be called whenever any value\n * in this storage instance changes (set or delete).\n *\n * To unsubscribe from value changes, call `remove()` on the Listener.\n */\n addOnValueChangedListener: (\n onValueChanged: (key: string) => void\n ) => Listener;\n}\n\nexport type NativeMMKV = Pick<\n MMKVInterface,\n | 'clearAll'\n | 'contains'\n | 'delete'\n | 'getAllKeys'\n | 'getBoolean'\n | 'getNumber'\n | 'getString'\n | 'set'\n | 'recrypt'\n>;\n\nconst onValueChangedListeners = new Map<string, ((key: string) => void)[]>();\n\n/**\n * A single MMKV instance.\n */\nexport class MMKV implements MMKVInterface {\n private nativeInstance: NativeMMKV;\n private functionCache: Partial<NativeMMKV>;\n private id: string;\n\n /**\n * Creates a new MMKV instance with the given Configuration.\n * If no custom `id` is supplied, `'mmkv.default'` will be used.\n */\n constructor(configuration: MMKVConfiguration = { id: 'mmkv.default' }) {\n this.id = configuration.id;\n this.nativeInstance = createMMKV(configuration);\n this.functionCache = {};\n }\n\n private get onValueChangedListeners() {\n if (!onValueChangedListeners.has(this.id)) {\n onValueChangedListeners.set(this.id, []);\n }\n return onValueChangedListeners.get(this.id)!;\n }\n\n private getFunctionFromCache<T extends keyof NativeMMKV>(\n functionName: T\n ): NativeMMKV[T] {\n if (this.functionCache[functionName] == null) {\n this.functionCache[functionName] = this.nativeInstance[functionName];\n }\n return this.functionCache[functionName] as NativeMMKV[T];\n }\n\n private onValuesChanged(keys: string[]) {\n if (this.onValueChangedListeners.length === 0) return;\n\n for (const key of keys) {\n for (const listener of this.onValueChangedListeners) {\n listener(key);\n }\n }\n }\n\n set(key: string, value: boolean | string | number): void {\n const func = this.getFunctionFromCache('set');\n func(key, value);\n\n this.onValuesChanged([key]);\n }\n getBoolean(key: string): boolean | undefined {\n const func = this.getFunctionFromCache('getBoolean');\n return func(key);\n }\n getString(key: string): string | undefined {\n const func = this.getFunctionFromCache('getString');\n return func(key);\n }\n getNumber(key: string): number | undefined {\n const func = this.getFunctionFromCache('getNumber');\n return func(key);\n }\n contains(key: string): boolean {\n const func = this.getFunctionFromCache('contains');\n return func(key);\n }\n delete(key: string): void {\n const func = this.getFunctionFromCache('delete');\n func(key);\n\n this.onValuesChanged([key]);\n }\n getAllKeys(): string[] {\n const func = this.getFunctionFromCache('getAllKeys');\n return func();\n }\n clearAll(): void {\n const keys = this.getAllKeys();\n\n const func = this.getFunctionFromCache('clearAll');\n func();\n\n this.onValuesChanged(keys);\n }\n recrypt(key: string | undefined): void {\n const func = this.getFunctionFromCache('recrypt');\n return func(key);\n }\n\n toString(): string {\n return `MMKV (${this.id}): [${this.getAllKeys().join(', ')}]`;\n }\n toJSON(): object {\n return {\n [this.id]: this.getAllKeys(),\n };\n }\n\n addOnValueChangedListener(onValueChanged: (key: string) => void): Listener {\n this.onValueChangedListeners.push(onValueChanged);\n\n return {\n remove: () => {\n const index = this.onValueChangedListeners.indexOf(onValueChanged);\n if (index !== -1) {\n this.onValueChangedListeners.splice(index, 1);\n }\n },\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["MMKV.ts"],"names":["createMMKV","createMockMMKV","isJest","onValueChangedListeners","Map","MMKV","constructor","configuration","id","nativeInstance","functionCache","has","set","get","getFunctionFromCache","functionName","onValuesChanged","keys","length","key","listener","value","func","getBoolean","getString","getNumber","contains","delete","getAllKeys","clearAll","recrypt","toString","join","toJSON","addOnValueChangedListener","onValueChanged","push","remove","index","indexOf","splice"],"mappings":"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","sourcesContent":["import { createMMKV } from './createMMKV';\nimport { createMockMMKV } from './createMMKV.mock';\nimport { isJest } from './PlatformChecker';\n\ninterface Listener {\n remove: () => void;\n}\n\n/**\n * Used for configuration of a single MMKV instance.\n */\nexport interface MMKVConfiguration {\n /**\n * The MMKV instance's ID. If you want to use multiple instances, make sure to use different IDs!\n *\n * @example\n * ```ts\n * const userStorage = new MMKV({ id: `user-${userId}-storage` })\n * const globalStorage = new MMKV({ id: 'global-app-storage' })\n * ```\n *\n * @default 'mmkv.default'\n */\n id: string;\n /**\n * The MMKV instance's root path. By default, MMKV stores file inside `$(Documents)/mmkv/`. You can customize MMKV's root directory on MMKV initialization:\n *\n * @example\n * ```ts\n * const temporaryStorage = new MMKV({ path: '/tmp/' })\n * ```\n */\n path?: string;\n /**\n * The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV.\n *\n * Encryption keys can have a maximum length of 16 bytes.\n *\n * @example\n * ```ts\n * const secureStorage = new MMKV({ encryptionKey: 'my-encryption-key!' })\n * ```\n */\n encryptionKey?: string;\n}\n\n/**\n * Represents a single MMKV instance.\n */\ninterface MMKVInterface {\n /**\n * Set a value for the given `key`.\n */\n set: (key: string, value: boolean | string | number) => void;\n /**\n * Get the boolean value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getBoolean: (key: string) => boolean | undefined;\n /**\n * Get the string value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getString: (key: string) => string | undefined;\n /**\n * Get the number value for the given `key`, or `undefined` if it does not exist.\n *\n * @default undefined\n */\n getNumber: (key: string) => number | undefined;\n /**\n * Checks whether the given `key` is being stored in this MMKV instance.\n */\n contains: (key: string) => boolean;\n /**\n * Delete the given `key`.\n */\n delete: (key: string) => void;\n /**\n * Get all keys.\n *\n * @default []\n */\n getAllKeys: () => string[];\n /**\n * Delete all keys.\n */\n clearAll: () => void;\n /**\n * Sets (or updates) the encryption-key to encrypt all data in this MMKV instance with.\n *\n * To remove encryption, pass `undefined` as a key.\n *\n * Encryption keys can have a maximum length of 16 bytes.\n */\n recrypt: (key: string | undefined) => void;\n /**\n * Adds a value changed listener. The Listener will be called whenever any value\n * in this storage instance changes (set or delete).\n *\n * To unsubscribe from value changes, call `remove()` on the Listener.\n */\n addOnValueChangedListener: (\n onValueChanged: (key: string) => void\n ) => Listener;\n}\n\nexport type NativeMMKV = Pick<\n MMKVInterface,\n | 'clearAll'\n | 'contains'\n | 'delete'\n | 'getAllKeys'\n | 'getBoolean'\n | 'getNumber'\n | 'getString'\n | 'set'\n | 'recrypt'\n>;\n\nconst onValueChangedListeners = new Map<string, ((key: string) => void)[]>();\n\n/**\n * A single MMKV instance.\n */\nexport class MMKV implements MMKVInterface {\n private nativeInstance: NativeMMKV;\n private functionCache: Partial<NativeMMKV>;\n private id: string;\n\n /**\n * Creates a new MMKV instance with the given Configuration.\n * If no custom `id` is supplied, `'mmkv.default'` will be used.\n */\n constructor(configuration: MMKVConfiguration = { id: 'mmkv.default' }) {\n this.id = configuration.id;\n this.nativeInstance = isJest()\n ? createMockMMKV()\n : createMMKV(configuration);\n this.functionCache = {};\n }\n\n private get onValueChangedListeners() {\n if (!onValueChangedListeners.has(this.id)) {\n onValueChangedListeners.set(this.id, []);\n }\n return onValueChangedListeners.get(this.id)!;\n }\n\n private getFunctionFromCache<T extends keyof NativeMMKV>(\n functionName: T\n ): NativeMMKV[T] {\n if (this.functionCache[functionName] == null) {\n this.functionCache[functionName] = this.nativeInstance[functionName];\n }\n return this.functionCache[functionName] as NativeMMKV[T];\n }\n\n private onValuesChanged(keys: string[]) {\n if (this.onValueChangedListeners.length === 0) return;\n\n for (const key of keys) {\n for (const listener of this.onValueChangedListeners) {\n listener(key);\n }\n }\n }\n\n set(key: string, value: boolean | string | number): void {\n const func = this.getFunctionFromCache('set');\n func(key, value);\n\n this.onValuesChanged([key]);\n }\n getBoolean(key: string): boolean | undefined {\n const func = this.getFunctionFromCache('getBoolean');\n return func(key);\n }\n getString(key: string): string | undefined {\n const func = this.getFunctionFromCache('getString');\n return func(key);\n }\n getNumber(key: string): number | undefined {\n const func = this.getFunctionFromCache('getNumber');\n return func(key);\n }\n contains(key: string): boolean {\n const func = this.getFunctionFromCache('contains');\n return func(key);\n }\n delete(key: string): void {\n const func = this.getFunctionFromCache('delete');\n func(key);\n\n this.onValuesChanged([key]);\n }\n getAllKeys(): string[] {\n const func = this.getFunctionFromCache('getAllKeys');\n return func();\n }\n clearAll(): void {\n const keys = this.getAllKeys();\n\n const func = this.getFunctionFromCache('clearAll');\n func();\n\n this.onValuesChanged(keys);\n }\n recrypt(key: string | undefined): void {\n const func = this.getFunctionFromCache('recrypt');\n return func(key);\n }\n\n toString(): string {\n return `MMKV (${this.id}): [${this.getAllKeys().join(', ')}]`;\n }\n toJSON(): object {\n return {\n [this.id]: this.getAllKeys(),\n };\n }\n\n addOnValueChangedListener(onValueChanged: (key: string) => void): Listener {\n this.onValueChangedListeners.push(onValueChanged);\n\n return {\n remove: () => {\n const index = this.onValueChangedListeners.indexOf(onValueChanged);\n if (index !== -1) {\n this.onValueChangedListeners.splice(index, 1);\n }\n },\n };\n }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ export function isJest() {
2
+ return process.env.JEST_WORKER_ID != null;
3
+ }
4
+ //# sourceMappingURL=PlatformChecker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["PlatformChecker.ts"],"names":["isJest","process","env","JEST_WORKER_ID"],"mappings":"AAAA,OAAO,SAASA,MAAT,GAA2B;AAChC,SAAOC,OAAO,CAACC,GAAR,CAAYC,cAAZ,IAA8B,IAArC;AACD","sourcesContent":["export function isJest(): boolean {\n return process.env.JEST_WORKER_ID != null;\n}\n"]}
@@ -0,0 +1,27 @@
1
+ /* Mock MMKV instance for use in tests */
2
+ export const createMockMMKV = () => {
3
+ const storage = new Map();
4
+ return {
5
+ clearAll: () => storage.clear(),
6
+ delete: key => storage.delete(key),
7
+ set: (key, value) => storage.set(key, value),
8
+ getString: key => {
9
+ const result = storage.get(key);
10
+ return typeof result === 'string' ? result : undefined;
11
+ },
12
+ getNumber: key => {
13
+ const result = storage.get(key);
14
+ return typeof result === 'number' ? result : undefined;
15
+ },
16
+ getBoolean: key => {
17
+ const result = storage.get(key);
18
+ return typeof result === 'boolean' ? result : undefined;
19
+ },
20
+ getAllKeys: () => Array.from(storage.keys()),
21
+ contains: key => storage.has(key),
22
+ recrypt: () => {
23
+ console.warn('Encryption is not supported in mocked MMKV instances!');
24
+ }
25
+ };
26
+ };
27
+ //# sourceMappingURL=createMMKV.mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["createMMKV.mock.ts"],"names":["createMockMMKV","storage","Map","clearAll","clear","delete","key","set","value","getString","result","get","undefined","getNumber","getBoolean","getAllKeys","Array","from","keys","contains","has","recrypt","console","warn"],"mappings":"AAEA;AACA,OAAO,MAAMA,cAAc,GAAG,MAAkB;AAC9C,QAAMC,OAAO,GAAG,IAAIC,GAAJ,EAAhB;AAEA,SAAO;AACLC,IAAAA,QAAQ,EAAE,MAAMF,OAAO,CAACG,KAAR,EADX;AAELC,IAAAA,MAAM,EAAGC,GAAD,IAASL,OAAO,CAACI,MAAR,CAAeC,GAAf,CAFZ;AAGLC,IAAAA,GAAG,EAAE,CAACD,GAAD,EAAME,KAAN,KAAgBP,OAAO,CAACM,GAAR,CAAYD,GAAZ,EAAiBE,KAAjB,CAHhB;AAILC,IAAAA,SAAS,EAAGH,GAAD,IAAS;AAClB,YAAMI,MAAM,GAAGT,OAAO,CAACU,GAAR,CAAYL,GAAZ,CAAf;AACA,aAAO,OAAOI,MAAP,KAAkB,QAAlB,GAA6BA,MAA7B,GAAsCE,SAA7C;AACD,KAPI;AAQLC,IAAAA,SAAS,EAAGP,GAAD,IAAS;AAClB,YAAMI,MAAM,GAAGT,OAAO,CAACU,GAAR,CAAYL,GAAZ,CAAf;AACA,aAAO,OAAOI,MAAP,KAAkB,QAAlB,GAA6BA,MAA7B,GAAsCE,SAA7C;AACD,KAXI;AAYLE,IAAAA,UAAU,EAAGR,GAAD,IAAS;AACnB,YAAMI,MAAM,GAAGT,OAAO,CAACU,GAAR,CAAYL,GAAZ,CAAf;AACA,aAAO,OAAOI,MAAP,KAAkB,SAAlB,GAA8BA,MAA9B,GAAuCE,SAA9C;AACD,KAfI;AAgBLG,IAAAA,UAAU,EAAE,MAAMC,KAAK,CAACC,IAAN,CAAWhB,OAAO,CAACiB,IAAR,EAAX,CAhBb;AAiBLC,IAAAA,QAAQ,EAAGb,GAAD,IAASL,OAAO,CAACmB,GAAR,CAAYd,GAAZ,CAjBd;AAkBLe,IAAAA,OAAO,EAAE,MAAM;AACbC,MAAAA,OAAO,CAACC,IAAR,CAAa,uDAAb;AACD;AApBI,GAAP;AAsBD,CAzBM","sourcesContent":["import type { NativeMMKV } from 'react-native-mmkv';\n\n/* Mock MMKV instance for use in tests */\nexport const createMockMMKV = (): NativeMMKV => {\n const storage = new Map<string, string | boolean | number>();\n\n return {\n clearAll: () => storage.clear(),\n delete: (key) => storage.delete(key),\n set: (key, value) => storage.set(key, value),\n getString: (key) => {\n const result = storage.get(key);\n return typeof result === 'string' ? result : undefined;\n },\n getNumber: (key) => {\n const result = storage.get(key);\n return typeof result === 'number' ? result : undefined;\n },\n getBoolean: (key) => {\n const result = storage.get(key);\n return typeof result === 'boolean' ? result : undefined;\n },\n getAllKeys: () => Array.from(storage.keys()),\n contains: (key) => storage.has(key),\n recrypt: () => {\n console.warn('Encryption is not supported in mocked MMKV instances!');\n },\n };\n};\n"]}
@@ -0,0 +1 @@
1
+ export declare function isJest(): boolean;
@@ -0,0 +1,2 @@
1
+ import type { NativeMMKV } from 'react-native-mmkv';
2
+ export declare const createMockMMKV: () => NativeMMKV;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mmkv",
3
- "version": "2.3.3",
3
+ "version": "2.4.2",
4
4
  "description": "The fastest key/value storage for React Native. ~30x faster than AsyncStorage! Works on Android, iOS and Web.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -30,6 +30,7 @@
30
30
  "lint-ci": "yarn lint -f ./node_modules/@firmnav/eslint-github-actions-formatter/dist/formatter.js",
31
31
  "prepare": "git submodule update --init --recursive",
32
32
  "build": "bob build",
33
+ "prepack": "bob build",
33
34
  "update-submodule": "git submodule update --remote --merge",
34
35
  "release": "release-it",
35
36
  "example": "yarn --cwd example",